[英]How to convert Object contains IList<class> which further contains 6 properties - 4 string, 1 IList<anotherclass>, 1 IList<string> to DataTable?
I am trying to convert my Object which have only 1 item (IList of class), this class contains 6 properties - 4 string, 1 IList of anotherClass and 1 IList of string.我正在尝试转换我的 Object ,它只有 1 个项目(类的 IList),这个 class 包含 6 个属性 - 4 个字符串,1 个 IList of anotherClass 和 1 个 IList of string。 I am using below generic method to convert:-
我正在使用以下通用方法进行转换:-
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;
}
At this point - dataTable.Rows.Add(values);此时 - dataTable.Rows.Add(values); I have the list values for 4 and 5 properties but when I add those to row, it shows text(type of property) in the row.
我有 4 和 5 个属性的列表值,但是当我将它们添加到行时,它会在行中显示文本(属性类型)。 While I need each item of 4 and 5 properties to come in next Row.
虽然我需要 4 和 5 个属性中的每一项才能进入下一行。 For Example:-
例如:-
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>)
I want below type of output:-我想要以下类型的 output:-
1String | 2String | 3String | 4String | Per | W |
:-----------|:------------:|:-----------:|:------------:|:---:|---:|
FirstString | SecondString | ThirdString | FourthString | 100 | 10W|
FirstString | SecondString | ThirdString | FourthString | 200 | 20W|
While the output I am currently getting is:-虽然我目前得到的 output 是:-
1String | 2String | 3String | 4String | Per | W |
:-----------|:------------:|:-----------:|:------------:|:--------------:|--------------:|
FirstString | SecondString | ThirdString | FourthString | typeofproperty | typeofproperty|
I just want my object's list to convert to DataTable.我只想将我的对象列表转换为 DataTable。
Below is the debugging result as per the solution given below:-以下是根据下面给出的解决方案的调试结果:-
@Dennis, Still getting type of property as value for list type property. @Dennis,仍然将属性类型作为列表类型属性的值。
Your code works fine for T
which contains only scalar properties (that is, primitive types, strings, dates, etc).您的代码适用于仅包含标量属性(即原始类型、字符串、日期等)的
T
When it deals with collection or nested object, it tries to store that object or collection in data table's row as is, so the result is not as you expected.当它处理集合或嵌套的 object 时,它会尝试将 object 或集合按原样存储在数据表的行中,因此结果与您预期的不一样。
To get the output you want, you need to flatten list items first.要获得您想要的 output,您需要先展平列表项。 Since
T
could be anything, flatten logic cannot be implemented in generic manner.由于
T
可以是任何东西,因此无法以通用方式实现展平逻辑。 But the caller can do this for you, since he knows everything about object structure.但是调用者可以为你做这件事,因为他对 object 结构了如指掌。
Having these types:有这些类型:
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; }
}
you can write this code:您可以编写以下代码:
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();
Result:结果:
As you can see, flatten logic inside SelectMany
depends on what T
is.如您所见,
SelectMany
中的展平逻辑取决于T
是什么。 If there will be, say, 3 nested lists and Bar
will contain public Boo { get; set; }
例如,如果有 3 个嵌套列表,并且
Bar
将包含public Boo { get; set; }
public Boo { get; set; }
public Boo { get; set; }
property, that logic will change to reflect new object structure. public Boo { get; set; }
属性,该逻辑将改变以反映新的 object 结构。
PS I've modified ToDataTable
definition a little to make it extension method for IEnumerable<T>
: PS 我稍微修改了
ToDataTable
定义,使其成为IEnumerable<T>
的扩展方法:
static class ConversionExtensions
{
public static DataTable ToDataTable<T>(this IEnumerable<T> items)
{
// your code here
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.