如何通过指定属性名称将通用对象列表转换为数据表? - C#

问题描述

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

      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>,它充当从您感兴趣的属性到其映射名称的映射。然后用这个来过滤对象的属性,建立数据表

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

,

MoreLINQ 包已经有一个适用于任何 IEnumerable<T>ToDataTable 方法。您可以使用 LINQ 的 Select 以您想要的任何方式塑造数据,然后使用 ToDataTable 将其转换为数据表:

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

另一个允许您填充已创建和配置的表。来自 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,但也许更好的解决方案是设置 Caption 属性。 Caption 的默认值为 ColumnName。带有空格的名称几乎肯定是为了显示目的。

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

例如:

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

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