c# - 如何将包含 IList<class> 的对象转换为 DataTable,该对象还包含 6 个属性 - 4 个字符串、1 个 IList<anotherclass>、1 个 IList<string> ?

标签 c# list object datatable

我正在尝试转换我的对象,它只有 1 个项目(类的 IList),该类包含 6 个属性 - 4 个字符串、1 个 anotherClass 的 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。

下面是根据下面给出的解决方案的调试结果:- enter image description here

@Dennis,仍在获取属性类型作为列表类型属性的值。 enter image description here

最佳答案

您的代码适用于 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();

结果:

enter image description here

如您所见,将 SelectMany 内部的逻辑扁平化取决于什么T是。比如说,如果有 3 个嵌套列表和 Bar将包含public Boo { get; set; }属性,该逻辑将改变以反射(reflect)新的对象结构。

附注我修改了ToDataTable稍微定义一下,使其成为 IEnumerable<T> 的扩展方法:

static class ConversionExtensions
{
    public static DataTable ToDataTable<T>(this IEnumerable<T> items)
    {
        // your code here
    }
}

关于c# - 如何将包含 IList<class> 的对象转换为 DataTable,该对象还包含 6 个属性 - 4 个字符串、1 个 IList<anotherclass>、1 个 IList<string> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65246243/

相关文章:

python - 在元组的第一个索引中查找具有非不同值的元组列表的索引

c++ - 模板集合的不同排序方法

java - 为什么我在战舰游戏中收到错误 java.lang.NullPointerException?

c# - 使用 Dapper 获取 UTC 日期时间

c# - 在 C# 中展平序列化 XML

python - 从 python 中的列表列表中删除列表项

Ruby Mechanize 网络爬虫库返回文件而不是页面

Java 空指针异常

c# - 编译会让我的敏感数据安全吗?

c# - 如何将条件编译符号 (DefineConstants) 传递给 msbuild