Using Reflection to create a DataTable from a Class?

后端 未结 9 1967
星月不相逢
星月不相逢 2020-12-02 07:39

I\'ve just learned about Generics and I\'m wondering whether I can use it to dynamically build datatables from my classes.

Or I might be missing the point here. Here

相关标签:
9条回答
  • 2020-12-02 08:07

    my favorite homemade function. it create and populate all at same time. throw any object.

     public static DataTable ObjectToData(object o)
     {
        DataTable dt = new DataTable("OutputData");
    
        DataRow dr = dt.NewRow();
        dt.Rows.Add(dr);
    
        o.GetType().GetProperties().ToList().ForEach(f =>
        {
            try
            {
                f.GetValue(o, null);
                dt.Columns.Add(f.Name, f.PropertyType);
                dt.Rows[0][f.Name] = f.GetValue(o, null);
            }
            catch { }
        });
        return dt;
     }
    
    0 讨论(0)
  • 2020-12-02 08:14

    Here's a VB.Net version that creates a data table from a generic list passed to the function as an object. There is also a helper function (ObjectToDataTable) that creates a data table from an object.

    Imports System.Reflection

       Public Shared Function ListToDataTable(ByVal _List As Object) As DataTable
    
        Dim dt As New DataTable
    
        If _List.Count = 0 Then
            MsgBox("The list cannot be empty. This is a requirement of the ListToDataTable function.")
            Return dt
        End If
    
        Dim obj As Object = _List(0)
        dt = ObjectToDataTable(obj)
        Dim dr As DataRow = dt.NewRow
    
        For Each obj In _List
    
            dr = dt.NewRow
    
            For Each p as PropertyInfo In obj.GetType.GetProperties
    
                dr.Item(p.Name) = p.GetValue(obj, p.GetIndexParameters)
    
            Next
    
            dt.Rows.Add(dr)
    
        Next
    
        Return dt
    
    End Function
    
    Public Shared Function ObjectToDataTable(ByVal o As Object) As DataTable
    
        Dim dt As New DataTable
        Dim properties As List(Of PropertyInfo) = o.GetType.GetProperties.ToList()
    
        For Each prop As PropertyInfo In properties
    
            dt.Columns.Add(prop.Name, prop.PropertyType)
    
        Next
    
        dt.TableName = o.GetType.Name
    
        Return dt
    
    End Function
    
    0 讨论(0)
  • 2020-12-02 08:16

    Here is a little bit modified code, which fixed time zone issue for datatime fields:

        public static DataTable ToDataTable<T>(this IList<T> data)
        {
            PropertyDescriptorCollection props =
                TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor prop = props[i];
                table.Columns.Add(prop.Name, prop.PropertyType);
            }
            object[] values = new object[props.Count];
            foreach (T item in data)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    if (props[i].PropertyType == typeof(DateTime))
                    {
                        DateTime currDT = (DateTime)props[i].GetValue(item);
                        values[i] = currDT.ToUniversalTime();
                    }
                    else
                    {
                        values[i] = props[i].GetValue(item);
                    }
                }
                table.Rows.Add(values);
            }
            return table;
        }
    
    0 讨论(0)
  • 2020-12-02 08:16

    Using the answer provided by @neoistheone I've changed the following sections. Works fine now.

    DataTable dogTable = new DataTable();
            dogTable = CreateDataTable(typeof(Dog));
    
            dogTable.Rows.Add(Killer.Breed, Killer.Name,Killer.legs,Killer.tail);
    
            foreach (DataRow row in dogTable.Rows)
            {
                Console.WriteLine(row.Field<string>("Name") + " " + row.Field<string>("Breed"));
                Console.ReadLine();
            }
    
    0 讨论(0)
  • 2020-12-02 08:17

    Here is a more compact version of David's answer that is also an extension function. I've posted the code in a C# project on Github.

    public static class Extensions
    {
        public static DataTable ToDataTable<T>(this IEnumerable<T> self)
        {
            var properties = typeof(T).GetProperties();
    
            var dataTable = new DataTable();
            foreach (var info in properties)
                dataTable.Columns.Add(info.Name, Nullable.GetUnderlyingType(info.PropertyType) 
                   ?? info.PropertyType);
    
            foreach (var entity in self)
                dataTable.Rows.Add(properties.Select(p => p.GetValue(entity)).ToArray());
    
            return dataTable;
        }     
    }
    

    I have found that this works very well in conjunction with code to write a DataTable to CSV.

    0 讨论(0)
  • 2020-12-02 08:18

    Building up on all the previous answers, here is a version that creates a DataTable from any collection:

    public static DataTable CreateDataTable<T>(IEnumerable<T> list)
    {
        Type type = typeof(T);
        var properties = type.GetProperties();      
    
        DataTable dataTable = new DataTable();
        foreach (PropertyInfo info in properties)
        {
            dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
        }
    
        foreach (T entity in list)
        {
            object[] values = new object[properties.Length];
            for (int i = 0; i < properties.Length; i++)
            {
                values[i] = properties[i].GetValue(entity);
            }
    
            dataTable.Rows.Add(values);
        }
    
        return dataTable;
    }
    
    0 讨论(0)
提交回复
热议问题