为了账号安全,请及时绑定邮箱和手机立即绑定

将IEnDigable转换为DataTable

将IEnDigable转换为DataTable

沧海一幻觉 2019-07-13 14:49:19
是否有一种很好的方法将IEnDigable转换为DataTable?我可以使用反射来获取属性和值,但这似乎有点低效,有内置的东西吗?(我知道这样的例子:ObtainDataTableFromIEnDigable)编辑:这,这个问题通知我处理空值有问题。下面我编写的代码正确地处理空值。public static DataTable ToDataTable<T>(this IEnumerable<T> items) {       // Create the result table, and gather all properties of a T             DataTable table = new DataTable(typeof(T).Name);      PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);       // Add the properties as columns to the datatable     foreach (var prop in props) {          Type propType = prop.PropertyType;          // Is it a nullable type? Get the underlying type          if (propType.IsGenericType && propType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))              propType = new NullableConverter(propType).UnderlyingType;           table.Columns.Add(prop.Name, propType);      }       // Add the property values per T as rows to the datatable     foreach (var item in items) {           var values = new object[props.Length];           for (var i = 0; i < props.Length; i++)              values[i] = props[i].GetValue(item, null);            table.Rows.Add(values);       }      return table; }
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

首先,您需要添加一个where T:class约束-你不能打电话GetValue关于值类型,除非它们是经过的ref.

第二GetValue很慢而且经常被打电话。

为了解决这个问题,我们可以创建一个委托,然后调用它:

MethodInfo method = property.GetGetMethod(true);Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), method );

问题是我们不知道TProperty,但像往常一样乔恩·斯基特有答案-我们可以使用反射检索getter委托,但是一旦有了它,我们就不需要再进行反射:

public class ReflectionUtility{
    internal static Func<object, object> GetGetter(PropertyInfo property)
    {
        // get the get method for the property
        MethodInfo method = property.GetGetMethod(true);

        // get the generic get-method generator (ReflectionUtility.GetSetterHelper<TTarget, TValue>)
        MethodInfo genericHelper = typeof(ReflectionUtility).GetMethod(
            "GetGetterHelper",
            BindingFlags.Static | BindingFlags.NonPublic);

        // reflection call to the generic get-method generator to generate the type arguments
        MethodInfo constructedHelper = genericHelper.MakeGenericMethod(
            method.DeclaringType,
            method.ReturnType);

        // now call it. The null argument is because it's a static method.
        object ret = constructedHelper.Invoke(null, new object[] { method });

        // cast the result to the action delegate and return it
        return (Func<object, object>) ret;
    }

    static Func<object, object> GetGetterHelper<TTarget, TResult>(MethodInfo method)
        where TTarget : class // target must be a class as property sets on structs need a ref param
    {
        // Convert the slow MethodInfo into a fast, strongly typed, open delegate
        Func<TTarget, TResult> func = (Func<TTarget, TResult>) Delegate.CreateDelegate(typeof(Func<TTarget, TResult>), method);

        // Now create a more weakly typed delegate which will call the strongly typed one
        Func<object, object> ret = (object target) => (TResult) func((TTarget) target);
        return ret;
    }}

现在,您的方法变成:

public static DataTable ToDataTable<T>(this IEnumerable<T> items) 
    where T: class{  
    // ... create table the same way

    var propGetters = new List<Func<T, object>>();foreach (var prop in props)
    {
        Func<T, object> func = (Func<T, object>) ReflectionUtility.GetGetter(prop);
        propGetters.Add(func);
    }

    // Add the property values per T as rows to the datatable
    foreach (var item in items) 
    {  
        var values = new object[props.Length];  
        for (var i = 0; i < props.Length; i++) 
        {
            //values[i] = props[i].GetValue(item, null);   
            values[i] = propGetters[i](item);
        }    

        table.Rows.Add(values);  
    } 

    return table; }

您可以通过在静态字典中存储每个类型的getter来进一步优化它,然后对每个类型只进行一次反射开销。


查看完整回答
反对 回复 2019-07-13
  • 3 回答
  • 0 关注
  • 662 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信