使用Reflection从类创建DataTable?

vwd*_*aal 30 .net c# oop reflection

我刚刚学习了Generics,我想知道我是否可以用它来动态地从我的类中构建数据表.

或者我可能会忽略这一点.这是我的代码,我要做的是从我现有的类创建一个数据表并填充它.但是我陷入了思考过程中.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

namespace Generics
{
    public class Dog
    {
        public string Breed { get; set; }
        public string Name { get; set; }
        public int legs { get; set; }
        public bool tail { get; set; }
    }

    class Program
    {
        public static DataTable CreateDataTable(Type animaltype)
        {
            DataTable return_Datatable = new DataTable();
            foreach (PropertyInfo info in animaltype.GetProperties())
            {
                return_Datatable.Columns.Add(new DataColumn(info.Name, info.PropertyType));
            }
            return return_Datatable;
        }

        static void Main(string[] args)
        {
            Dog Killer = new Dog();
            Killer.Breed = "Maltese Poodle";
            Killer.legs = 3;
            Killer.tail = false;
            Killer.Name = "Killer";

            DataTable dogTable = new DataTable();
            dogTable = CreateDataTable(Dog);
//How do I continue from here?


        }      
    }
}    
Run Code Online (Sandbox Code Playgroud)

现在,DataTable它出错了.另外,作为反射和泛型的新手,我将如何使用Killer类实际填充数据?

Dav*_*yan 81

在所有以前的答案的基础上,这是一个从任何集合创建DataTable的版本:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 很棒,我在一年多的时间里没有碰过那部分代码,但这恰好是我正在做的其他事情.谢谢大卫 (3认同)

Fra*_*nck 8

我最喜欢的自制功能.它可以同时创建和填充所有内容.抛出任何物体.

 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;
 }
Run Code Online (Sandbox Code Playgroud)


cdi*_*ins 8

这是David答案的更紧凑版本,它也是扩展功能。我已经在GithubC#项目中发布了代码。

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;
    }     
}
Run Code Online (Sandbox Code Playgroud)

我发现,这与将DataTable写入CSV的代码结合使用非常有效。


Mik*_*oud 5

该错误可以通过更改以下内容来解决:

dogTable = CreateDataTable(Dog);
Run Code Online (Sandbox Code Playgroud)

对此:

dogTable = CreateDataTable(typeof(Dog));
Run Code Online (Sandbox Code Playgroud)

但您尝试做的事情有一些警告。首先, aDataTable不能存储复杂类型,因此如果它Dog有一个实例Cat,您将无法将其添加为列。在这种情况下,你想做什么取决于你,但请记住这一点。

其次,我建议您使用 a 的唯一时间DataTable是当您构建对其所消耗的数据一无所知的代码时。这有有效的用例(例如用户驱动的数据挖掘工具)。如果实例中已有数据Dog,则只需使用它即可。

另一个小花絮,是这样的:

DataTable dogTable = new DataTable();
dogTable = CreateDataTable(Dog);
Run Code Online (Sandbox Code Playgroud)

可以简化为:

DataTable dogTable = CreateDataTable(Dog);
Run Code Online (Sandbox Code Playgroud)