c# - 如何转换对象包含 IList其中还包含 6 个属性 - 4 个字符串,1 个 IList, 1 个 IList到数据表?
问题描述
我正在尝试转换只有 1 个项目(类的 IList)的对象,该类包含 6 个属性 - 4 个字符串、1 个另一个类的 IList 和 1 个字符串的 IList。我正在使用以下通用方法进行转换:-
public static DataTable ToDataTable<T>(IList<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Defining type of data column gives proper data table
var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
//Setting column names as Property names
dataTable.Columns.Add(prop.Name, type);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}
此时 - dataTable.Rows.Add(values); 我有 4 和 5 个属性的列表值,但是当我将它们添加到行时,它会在行中显示文本(属性类型)。虽然我需要 4 和 5 个属性中的每一项才能进入下一行。例如 :-
values[0] - "FirstString",
values[1] - "SecondString",
values[2] - "ThirdString",
values[3] - "FourthString",
values[4] - Count 2 - 100, 200 (IList<AnotherClass>()),
values [5] - Count 2 - "10W", "20W" (IList<string>)
我想要以下类型的输出:-
1String | 2String | 3String | 4String | Per | W |
:-----------|:------------:|:-----------:|:------------:|:---:|---:|
FirstString | SecondString | ThirdString | FourthString | 100 | 10W|
FirstString | SecondString | ThirdString | FourthString | 200 | 20W|
虽然我目前得到的输出是: -
1String | 2String | 3String | 4String | Per | W |
:-----------|:------------:|:-----------:|:------------:|:--------------:|--------------:|
FirstString | SecondString | ThirdString | FourthString | typeofproperty | typeofproperty|
我只想将我的对象列表转换为 DataTable。
解决方案
您的代码适用于T
仅包含标量属性(即原始类型、字符串、日期等)的代码。
当它处理集合或嵌套对象时,它会尝试将该对象或集合按原样存储在数据表的行中,因此结果与您预期的不一样。
要获得所需的输出,您需要先展平列表项。由于T
可以是任何东西,因此无法以通用方式实现展平逻辑。但是调用者可以为你做这件事,因为他对对象结构了如指掌。
有这些类型:
class Foo
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public IList<Bar> Bars { get; set; }
public IList<string> Strings { get; set; }
}
class Bar
{
public int A { get; set; }
}
您可以编写以下代码:
var items = new List<Foo>
{
new Foo
{
A = "FirstString",
B = "SecondString",
C = "ThirdString",
D = "FourthString",
Bars = new List<Bar>
{
new Bar { A = 100 },
new Bar { A = 200 }
},
Strings = new List<string>
{
"10W",
"20W"
}
}
};
var dataTable = items
.SelectMany(item => item.Bars.Zip(item.Strings, (bar, stringValue) => new
{
BarA = bar.A,
StringValue = stringValue
}),
(item, _) => new
{
item.A,
item.B,
item.C,
item.D,
_.BarA,
_.StringValue
})
.ToDataTable();
结果:
如您所见,内部的扁平化逻辑SelectMany
取决于是什么T
。例如,如果有 3 个嵌套列表并Bar
包含public Boo { get; set; }
属性,则该逻辑将更改以反映新的对象结构。
PS我已经ToDataTable
稍微修改了定义以使其扩展方法IEnumerable<T>
:
static class ConversionExtensions
{
public static DataTable ToDataTable<T>(this IEnumerable<T> items)
{
// your code here
}
}
推荐阅读
- search - intelliJ -> 有什么方法可以将您的搜索范围限定在一个函数内
- nlp - Python PYPDF2:'utf-8'编解码器无法解码位置 395 的字节 0x80:无效的起始字节
- python - 将大型镶木地板文件转换为 csv
- android - Xamarin.forms.ListView - GroupHeader - 我们可以在父级边界之外绘制吗
- javascript - 如果 JSON 字段为空,如何将空数组字段附加到 JSON 中?
- python-3.x - 我如何给棋盘的正方形大小进行校准?
- openmdao - Openmdao:如何停用约束?
- r - summarise_all 的平均值或最大值取决于 dplyr 的值?
- c# - 无法统一从另一个 C# 脚本访问变量
- asp.net-core - 如何仅在扩展授权类型中添加自定义声明