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

将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 回答

?
收到一只叮咚

看看这个:将List/IEnDigable转换为DataTable/DataView

在我的代码中,我将它更改为一个扩展方法:

public static DataTable ToDataTable<T>(this List<T> items){
    var tb = new DataTable(typeof(T).Name);

    PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach(var prop in props)
    {
        tb.Columns.Add(prop.Name, prop.PropertyType);
    }

     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);
        }

        tb.Rows.Add(values);
    }

    return tb;}


查看完整回答
反对 回复 2019-07-13
?
ITMISS

致所有人:

请注意,接受的答案中存在一个与可空类型和DataTable相关的错误。此修复程序可在链接的站点(http:/www.chinhdo.com/20090402/转换-列表到-dataTable/)或在下面修改的代码中:

    ///###############################################################
    /// <summary>
    /// Convert a List to a DataTable.
    /// </summary>
    /// <remarks>
    /// Based on MIT-licensed code presented at http://www.chinhdo.com/20090402/convert-list-to-datatable/ as "ToDataTable"
    /// <para/>Code modifications made by Nick Campbell.
    /// <para/>Source code provided on this web site (chinhdo.com) is under the MIT license.
    /// <para/>Copyright © 2010 Chinh Do
    /// <para/>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
    files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
     merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished 
     to do so, subject to the following conditions:
    /// <para/>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Sof
    tware.
    /// <para/>THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE W
    ARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLD
    ERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O
    R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    /// <para/>(As per http://www.chinhdo.com/20080825/transactional-file-manager/)
    /// </remarks>
    /// <typeparam name="T">Type representing the type to convert.</typeparam>
    /// <param name="l_oItems">List of requested type representing the values to convert.</param>
    /// <returns></returns>
    ///###############################################################
    /// <LastUpdated>February 15, 2010</LastUpdated>
    public static DataTable ToDataTable<T>(List<T> l_oItems) {
        DataTable oReturn = new DataTable(typeof(T).Name);
        object[] a_oValues;
        int i;

            //#### Collect the a_oProperties for the passed T
        PropertyInfo[] a_oProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            //#### Traverse each oProperty, .Add'ing each .Name/.BaseType into our oReturn value
            //####     NOTE: The call to .BaseType is required as DataTables/DataSets do not support nullable types, so it's non
            -nullable counterpart Type is required in the .Column definition
        foreach(PropertyInfo oProperty in a_oProperties) {
            oReturn.Columns.Add(oProperty.Name, BaseType(oProperty.PropertyType));
        }

            //#### Traverse the l_oItems
        foreach (T oItem in l_oItems) {
                //#### Collect the a_oValues for this loop
            a_oValues = new object[a_oProperties.Length];

                //#### Traverse the a_oProperties, populating each a_oValues as we go
            for (i = 0; i < a_oProperties.Length; i++) {
                a_oValues[i] = a_oProperties[i].GetValue(oItem, null);
            }

                //#### .Add the .Row that represents the current a_oValues into our oReturn value
            oReturn.Rows.Add(a_oValues);
        }

            //#### Return the above determined oReturn value to the caller
        return oReturn;
    }

    ///###############################################################
    /// <summary>
    /// Returns the underlying/base type of nullable types.
    /// </summary>
    /// <remarks>
    /// Based on MIT-licensed code presented at http://www.chinhdo.com/20090402/convert-list-to-datatable/ as "GetCoreType"
    /// <para/>Code modifications made by Nick Campbell.
    /// <para/>Source code provided on this web site (chinhdo.com) is under the MIT license.
    /// <para/>Copyright © 2010 Chinh Do
    /// <para/>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
     files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
      merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished 
      to do so, subject to the following conditions:
    /// <para/>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    /// <para/>THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARR
    ANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONN
     ECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    /// <para/>(As per http://www.chinhdo.com/20080825/transactional-file-manager/)
    /// </remarks>
    /// <param name="oType">Type representing the type to query.</param>
    /// <returns>Type representing the underlying/base type.</returns>
    ///###############################################################
    /// <LastUpdated>February 15, 2010</LastUpdated>
    public static Type BaseType(Type oType) {
            //#### If the passed oType is valid, .IsValueType and is logicially nullable, .Get(its)UnderlyingType
        if (oType != null && oType.IsValueType &&
            oType.IsGenericType && oType.GetGenericTypeDefinition() == typeof(Nullable<>)
        ) {
            return Nullable.GetUnderlyingType(oType);
        }
            //#### Else the passed oType was null or was not logicially nullable, so simply return the passed oType
        else {
            return oType;
        }
    }

请注意,这两个示例都是像上面的例子一样的扩展方法。

最后.。为我的广泛/过度的评论道歉(我有一个肛门/卑劣的教授对我的打击!)


查看完整回答
反对 回复 2019-07-13
?
LEATH

首先,您需要添加一个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

添加回答

回复

举报

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