C# 如何转换包含IList的对象<;类别>;它还包含6个属性-4个字符串,1个IList<;另一类>;,1 IList<;字符串>;到数据表?

C# 如何转换包含IList的对象<;类别>;它还包含6个属性-4个字符串,1个IList<;另一类>;,1 IList<;字符串>;到数据表?,c#,list,object,datatable,C#,List,Object,Datatable,我试图转换我的对象,它只有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 properti

我试图转换我的对象,它只有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;
    }
而我目前得到的输出是:-

1String     | 2String      | 3String     | 4String      | Per            | W                 |
:-----------|:------------:|:-----------:|:------------:|:--------------:|--------------:|
FirstString | SecondString | ThirdString | FourthString | typeofproperty | typeofproperty|
我只想将对象的列表转换为DataTable

下面是根据下面给出的解决方案进行调试的结果:-

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

对于只包含标量属性(即基元类型、字符串、日期等)的
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; }
}

您需要首先展平对象以使代码正常工作。用一般的方式来做这件事并不容易,因为t可以是任何东西,就像扁平化逻辑一样。如果
仅具有标量属性(我的意思是没有集合或其他嵌套对象)就可以转换为DTO,那么就容易多了。此方法的调用是toDataTable(IList)。我怎样才能把物体展平?打电话的人必须这样做。否则它就不会是微不足道的。另一个选项是对
T
结构进行限制(例如,仅2个列表,列表长度相同),但在这种情况下,通用转换器没有意义。您好,示例中的item.Strings和stringValue是什么?item.bar.Zip(item.Strings,(bar,stringValue)=>new{BarA=bar.A,stringValue=stringValue})
item.Strings
Foo
类中的
IList
属性
stringValue
item.Strings
的一项。我猜,你问的主要是关于
Zip
方法-它只是由两个不同类型的序列组成第三个序列。从字面上说,是成对的序列(100,“10W”),(200,“20W”)。是的,这是可行的,但在定义了项之后,它不允许我调用ToDataTable()方法。让我定义类型。你知道吗?@EktaC,我不知道你修改过的代码是什么样子如果你可以发布或分享,请这样做。请看下面我提供的截图。
1String     | 2String      | 3String     | 4String      | Per            | W                 |
:-----------|:------------:|:-----------:|:------------:|:--------------:|--------------:|
FirstString | SecondString | ThirdString | FourthString | typeofproperty | typeofproperty|
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();
static class ConversionExtensions
{
    public static DataTable ToDataTable<T>(this IEnumerable<T> items)
    {
        // your code here
    }
}