将IEnDigable转换为DataTable

是否有一种很好的方法将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; }


沧海一幻觉
浏览 663回答 3
3回答

LEATH

首先,您需要添加一个where T:class约束-你不能打电话GetValue关于值类型,除非它们是经过的ref.第二GetValue很慢而且经常被打电话。为了解决这个问题,我们可以创建一个委托,然后调用它:MethodInfo&nbsp;method&nbsp;=&nbsp;property.GetGetMethod(true);Delegate.CreateDelegate(typeof(Func<TClass,&nbsp;TProperty>),&nbsp;method&nbsp;);问题是我们不知道TProperty,但像往常一样乔恩·斯基特有答案-我们可以使用反射检索getter委托,但是一旦有了它,我们就不需要再进行反射:public&nbsp;class&nbsp;ReflectionUtility{ &nbsp;&nbsp;&nbsp;&nbsp;internal&nbsp;static&nbsp;Func<object,&nbsp;object>&nbsp;GetGetter(PropertyInfo&nbsp;property) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;get&nbsp;the&nbsp;get&nbsp;method&nbsp;for&nbsp;the&nbsp;property &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodInfo&nbsp;method&nbsp;=&nbsp;property.GetGetMethod(true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;get&nbsp;the&nbsp;generic&nbsp;get-method&nbsp;generator&nbsp;(ReflectionUtility.GetSetterHelper<TTarget,&nbsp;TValue>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodInfo&nbsp;genericHelper&nbsp;=&nbsp;typeof(ReflectionUtility).GetMethod( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"GetGetterHelper", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BindingFlags.Static&nbsp;|&nbsp;BindingFlags.NonPublic); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;reflection&nbsp;call&nbsp;to&nbsp;the&nbsp;generic&nbsp;get-method&nbsp;generator&nbsp;to&nbsp;generate&nbsp;the&nbsp;type&nbsp;arguments &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodInfo&nbsp;constructedHelper&nbsp;=&nbsp;genericHelper.MakeGenericMethod( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.DeclaringType, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.ReturnType); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;now&nbsp;call&nbsp;it.&nbsp;The&nbsp;null&nbsp;argument&nbsp;is&nbsp;because&nbsp;it's&nbsp;a&nbsp;static&nbsp;method. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object&nbsp;ret&nbsp;=&nbsp;constructedHelper.Invoke(null,&nbsp;new&nbsp;object[]&nbsp;{&nbsp;method&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;cast&nbsp;the&nbsp;result&nbsp;to&nbsp;the&nbsp;action&nbsp;delegate&nbsp;and&nbsp;return&nbsp;it &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(Func<object,&nbsp;object>)&nbsp;ret; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;Func<object,&nbsp;object>&nbsp;GetGetterHelper<TTarget,&nbsp;TResult>(MethodInfo&nbsp;method) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;TTarget&nbsp;:&nbsp;class&nbsp;//&nbsp;target&nbsp;must&nbsp;be&nbsp;a&nbsp;class&nbsp;as&nbsp;property&nbsp;sets&nbsp;on&nbsp;structs&nbsp;need&nbsp;a&nbsp;ref&nbsp;param &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Convert&nbsp;the&nbsp;slow&nbsp;MethodInfo&nbsp;into&nbsp;a&nbsp;fast,&nbsp;strongly&nbsp;typed,&nbsp;open&nbsp;delegate &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Func<TTarget,&nbsp;TResult>&nbsp;func&nbsp;=&nbsp;(Func<TTarget,&nbsp;TResult>)&nbsp;Delegate.CreateDelegate(typeof(Func<TTarget,&nbsp;TResult>),&nbsp;method); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Now&nbsp;create&nbsp;a&nbsp;more&nbsp;weakly&nbsp;typed&nbsp;delegate&nbsp;which&nbsp;will&nbsp;call&nbsp;the&nbsp;strongly&nbsp;typed&nbsp;one &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Func<object,&nbsp;object>&nbsp;ret&nbsp;=&nbsp;(object&nbsp;target)&nbsp;=>&nbsp;(TResult)&nbsp;func((TTarget)&nbsp;target); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ret; &nbsp;&nbsp;&nbsp;&nbsp;}}现在,您的方法变成:public&nbsp;static&nbsp;DataTable&nbsp;ToDataTable<T>(this&nbsp;IEnumerable<T>&nbsp;items)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;T:&nbsp;class{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...&nbsp;create&nbsp;table&nbsp;the&nbsp;same&nbsp;way &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;propGetters&nbsp;=&nbsp;new&nbsp;List<Func<T,&nbsp;object>>();foreach&nbsp;(var&nbsp;prop&nbsp;in&nbsp;props) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Func<T,&nbsp;object>&nbsp;func&nbsp;=&nbsp;(Func<T,&nbsp;object>)&nbsp;ReflectionUtility.GetGetter(prop); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;propGetters.Add(func); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Add&nbsp;the&nbsp;property&nbsp;values&nbsp;per&nbsp;T&nbsp;as&nbsp;rows&nbsp;to&nbsp;the&nbsp;datatable &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;item&nbsp;in&nbsp;items)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;values&nbsp;=&nbsp;new&nbsp;object[props.Length];&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;props.Length;&nbsp;i++)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//values[i]&nbsp;=&nbsp;props[i].GetValue(item,&nbsp;null);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values[i]&nbsp;=&nbsp;propGetters[i](item); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Rows.Add(values);&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;table;&nbsp;}您可以通过在静态字典中存储每个类型的getter来进一步优化它,然后对每个类型只进行一次反射开销。
打开App,查看更多内容
随时随地看视频慕课网APP