如何通过指定 属性 名称将通用 Object 列表转换为 DataTable? - C#

How to convert a generic Object List to DataTable by specifying Property Name? - C#

我创建了一个将 List 转换为 Datatable 的函数。但是我需要自定义此函数,以便该方法将具有列表属性(例如:Name,Age)的附加参数,这些参数仅在转换为数据表时才被考虑。我还想保持列的顺序与它们在 属性 列表中的顺序相同。示例 - 我正在传递列表(具有不同属性名称、年龄、出生日期、地点的客户)和要转换的属性列表,即列表(名称、年龄)。我还想将名称的数据表列 Header 重命名为“人名”和年龄为“人的年龄”。任何人都可以帮助我如何实现 this.Also 你可以提出更好的逻辑来实现要求。

      public DataTable ToDataTable<T>(List<T> items)
        {
            DataTable dataTable = new DataTable(typeof(T).Name);
                    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo prop in Props)
            {
                //Setting column names as Property names  
                dataTable.Columns.Add(prop.Name);
            }
            foreach (T item in items)
            {
                var values = new object[Props.Length];
                for (int i = 0; i < Props.Length; i++)
                {

                    values[i] = Props[i].GetValue(item, null);
                }
                dataTable.Rows.Add(values);
            }

            return dataTable;
        }

我建议您更改您的方法以采用 Dictionary<string,string> 作为您感兴趣的属性到其映射名称的映射。然后使用它从对象中过滤属性并构建数据table

public static DataTable ToDataTable<T>(List<T> items, Dictionary<string,string> properties)
{
    DataTable dataTable = new DataTable(typeof(T).Name);
    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                               .Where(p => properties.ContainsKey(p.Name)).ToArray();
    foreach (PropertyInfo prop in Props)
    {
        //Setting column names as Property names  
        dataTable.Columns.Add(properties[prop.Name]);
    }
    foreach (T item in items)
    {
        var values = new object[Props.Length];
        for (int i = 0; i < Props.Length; i++)
        {

            values[i] = Props[i].GetValue(item, null);
        }
        dataTable.Rows.Add(values);
    }

    return dataTable;
}

然后你可以这样做:

var props = new Dictionary<string,string>
{ 
    ["Name"] = "Person Name",
    ["Age"] = "Person Age"
};
var dt = ToDataTable(people, props);

实例:https://dotnetfiddle.net/7XkJvV

适用于任何 IEnumerable<T>MoreLINQ package already has a ToDataTable 方法。您可以使用 LINQ 的 Select 以任何您想要的方式塑造数据,然后使用 ToDataTable :

将其转换为 DataTable
var table= customers.Select (customer => new {
               customer.Name,
               customer.DOB,
               Age=(DateTime.Today-customer.DOB).Days/365
           })
           .ToDataTable();

ToDataTable 有一个重载,允许您通过表达式指定要使用的属性:

var table=customers.ToDataTable(new[]{ c=>c.Name, c=>c.DOB });

另一个允许您填充已创建和配置的 table。来自 the unit tests 之一:

var dt = new DataTable();
var columns = dt.Columns;
columns.Add("Column1", typeof(int));
columns.Add("Value", typeof(string));
columns.Add("Column3", typeof(int));
columns.Add("Name", typeof(string));

var vars = Environment.GetEnvironmentVariables()
                      .Cast<DictionaryEntry>()
                      .ToArray();

vars.Select(e => new { Name = e.Key.ToString(), 
                       Value = e.Value.ToString() })
    .ToDataTable(dt, e => e.Name, e => e.Value);

带空格的列

您可以更改 DataColumn.ColumnName afterwards but perhaps a better solution would be to set the Caption 属性。 Caption 的默认值是 ColumnName。带有空格的名称几乎肯定是为了显示目的。

最好不要修改 ColumnName,这样您就可以按名称识别列,并将显示标题更改为您需要的任何内容。

例如:

var personColumns=new[]{"Name","Age"};

foreach(DataColumn column in table.Columns)
{
    column.Caption = $"Person {column.ColumnName}";
}