gpt4 book ai didi

c# - 将通用嵌套列表转换为数据表

转载 作者:行者123 更新时间:2023-11-30 23:33:42 26 4
gpt4 key购买 nike

Continuation from "Convert generic List/Enumerable to DataTable?"

我一直在使用以下代码来隐藏通用 List<T>进入DataTable :

    public static DataTable ToDataTable<T>(this IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}

但是,我现在有一个列表 List<foo>其中 foo包含属性 List<bar> (其中 List<bar> 可以包含零值)。

问题:

我想转换一个通用的 List<foo>包含另一个通用嵌套 List<bar>例如:

        List<bar> GenericNestedList = new List<bar>{ new bar("barA"), new bar("barB") };
List<foo> GenericList = new List<foo> { new foo("fooA", GenericNestedList) };

结果是 DataTable :

| GenericProperty | GenericNestedProperty |
|-----------------|-----------------------|
| fooA | barA |
| fooA | barB |

原始代码说明了 foo 中的许多属性, bar也会有这个要求。

到目前为止,我已经能够检索到 bar 的属性,但是我一直无法弄清楚如何填充 Datatable什么时候List<bar>是空的。我没有很多编写通用方法的经验,所以很抱歉无法提供我的很多工作。

其他示例:

列表

List<foo> GenericList = new List<foo> { new foo("fooB", new List<bar>()) };

数据表

| GenericProperty | GenericNestedProperty |
|-----------------|-----------------------|
| fooB | |

列表

        List<bar> GenericNestedListA = new List<bar>{ new bar("barC"), new bar("barD") };
List<bar> GenericNestedListB = new List<bar> { new bar("barE"), new bar("barF") };

List<foo> GenericList = new List<foo> { new foo("fooC", GenericNestedListA),
new foo("fooD", GenericNestedListB) };

数据表

| GenericProperty | GenericNestedProperty |
|-----------------|-----------------------|
| fooC | barC |
| fooC | barD |
| fooD | barE |
| fooD | barF |

类:

class foo
{
public string GenericProperty;
public List<bar> GenericNestedList;

public foo(string GenericProperty, List<bar> GenericNestedList)
{
this.GenericProperty = GenericProperty;
this.GenericNestedList = GenericNestedList;
}
}

class bar
{
public string GenericNestedProperty;

public bar(string GenericNestedProperty)
{
this.GenericNestedProperty = GenericNestedProperty;
}
}

最佳答案

只是一个快速的解决方案:

public DataTable CreateNestedDataTable<TOuter, TInner>(IEnumerable<TOuter> list, string innerListPropertyName)
{
PropertyInfo[] outerProperties = typeof(TOuter).GetProperties().Where(pi => pi.Name != innerListPropertyName).ToArray();
PropertyInfo[] innerProperties = typeof(TInner).GetProperties();
MethodInfo innerListGetter = typeof(TOuter).GetProperty(innerListPropertyName).GetMethod;

// set up columns
DataTable table = new DataTable();
foreach (PropertyInfo pi in outerProperties)
table.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType);
foreach (PropertyInfo pi in innerProperties)
table.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType);

// iterate through outer items
foreach (TOuter outerItem in list)
{
var innerList = innerListGetter.Invoke(outerItem, null) as IEnumerable<TInner>;
if (innerList == null || innerList.Count() == 0)
{
// outer item has no inner items
DataRow row = table.NewRow();
foreach (PropertyInfo pi in outerProperties)
row[pi.Name] = pi.GetValue(outerItem) ?? DBNull.Value;
table.Rows.Add(row);
}
else
{
// iterate through inner items
foreach (object innerItem in innerList)
{
DataRow row = table.NewRow();
foreach (PropertyInfo pi in outerProperties)
row[pi.Name] = pi.GetValue(outerItem) ?? DBNull.Value;
foreach (PropertyInfo pi in innerProperties)
row[pi.Name] = pi.GetValue(innerItem) ?? DBNull.Value;
table.Rows.Add(row);
}
}
}

return table;
}

有人可能会进一步扩展它,因此它可以处理多个嵌套列表,或者自动识别嵌套列表的属性。但我在这里保持简单。

它的用法是这样的:

var table = CreateNestedDataTable<foo, bar>(GenericList, "GenericNestedList");

用你的例子测试,它产生了预期的结果:

Desired results


以上代码使用了 .NET 4.5 引入的 PropertyInfo.GetMethodPropertyInfo.GetValue。对于 4.0,进行以下替换:

// before
typeof(TOuter).GetProperty(innerListPropertyName).GetMethod;

// after
typeof(TOuter).GetProperty(innerListPropertyName).GetGetMethod(true);


// for each row assignment
// before
row[pi.Name] = pi.GetValue(item) ?? DBNull.Value;

// after
row[pi.Name] = pi.GetValue(item, null) ?? DBNull.Value;

关于c# - 将通用嵌套列表转换为数据表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33823820/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com