如何通过指定 属性 名称将通用 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);
适用于任何 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}";
}
我创建了一个将 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);
适用于任何 IEnumerable<T>
的 MoreLINQ package already has a 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 });
另一个允许您填充已创建和配置的 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}";
}