简体   繁体   English

C# Core Get Generic Class T of Generic List<t></t>

[英]C# Core Get Generic Class T of Generic List<T>

I know how to loop through all properties of a class, but what if on property are List, how can I loop through all properties of T class?我知道如何遍历 class 的所有属性,但是如果属性是列表怎么办,我如何遍历 T class 的所有属性? See comments in my code.请参阅我的代码中的注释。 I have read 20 of the suggested similar questions but I don't get any answer.我已经阅读了 20 个建议的类似问题,但没有得到任何答案。 Either I am stupid and this is a duplicate (sorry for that in that case) or the answer is needed.要么我很愚蠢,这是重复的(在那种情况下很抱歉),要么需要答案。

public class HeaderClass
{
    public int HeaderId { get; set; }
    public string HeaderText { get; set; }  
    public string HeaderText2 { get; set; } 
    public RowClass Rows { get; set; }  
}

public class RowClass
{
    public int HeaderId { get; set; }
    public int SubRowId { get; set; }
    public string SubText { get; set; } 
    public string SubText2 { get; set; }    
}

//Call this to get all properties of HeaderClass
Getdata(Headers);

void Getdata(object myObject)
{
    foreach (PropertyInfo pi in myObject.GetType().GetProperties())
    {
        string currentPropertyName = pi.Name;
        string currentPropertyType;

        //First of all, are there a better way to direct get the TypeName?
        if(pi.PropertyType == typeof(string))
        {
            currentPropertyType = "string";
        }
        else if(pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(bool?))
        {
            currentPropertyType = "bool";
        }
        else if(pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
        {
            currentPropertyType = "DateTime";
        }


        //If the Type is List<T>
        if(pi.PropertyType.Name.ToLower() == "list`1")
        {
            Type itemType = pi.PropertyType.GetGenericArguments()[0];
            //How to convert this to an object so I can loop through all properties of class SubRows
        }
    }
}

You can get all properties of list type like this您可以像这样获取列表类型的所有属性

if(pi.PropertyType.IsGenericType && !pi.PropertyType.Name.Equals("Nullable`1"))
// or if(pi.PropertyType.Name.ToLower() == "list`1")
{
    foreach (var property in pi.PropertyType.GenericTypeArguments[0]
           .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                             // BindingFlags.DeclaredOnly => Inherited members are not considered
    {

    }
}

First of all you should not check the name, use pt.GetGenericTypeDefinition() == typeof(List<>) , second try this:首先你不应该检查名称,使用pt.GetGenericTypeDefinition() == typeof(List<>) ,然后试试这个:

class Foo
{
    public List<Bar> Bars {get;set;}
}

class Bar
{
    public int I1 { get; set; }
    public string S1 { get; set; }
}

var x = new Foo
{
    Bars = new List<Bar> { new Bar { S1 = "asdd"}}
};
foreach (var prop in typeof(Foo).GetProperties())
{

    var pt = prop.PropertyType;
    if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(List<>))
    {
        var en = (prop.GetValue(x) as IEnumerable).Cast<object>();

        var innerType = pt.GetGenericArguments()[0];
        foreach (var innerProp in innerType.GetProperties())
        {
            Console.WriteLine(innerProp.Name); // prints I1 S1
            Console.WriteLine(innerProp.GetValue(en.First())); // prints "asdd"
        }
    }
}

How to convert this to an object so I can loop thrue all properties of class SubRows如何将其转换为 object 以便我可以遍历 class 子行的所有属性

So you don't need to convert it to object, pi.PropertyType.GetGenericArguments()[0] returns you an instance of Type which has .GetProperties() method on it.因此,您无需将其转换为 object, pi.PropertyType.GetGenericArguments()[0]会返回一个Type实例,其中包含.GetProperties()方法。

static void GetData(object myObject)
{
    foreach (PropertyInfo pi in myObject.GetType().GetProperties())
    {
        string currentPropertyType;

        Console.WriteLine(pi.Name);

        //First of all, are there a better way to direct get the TypeName?
        if (pi.PropertyType == typeof(string))
        {
            currentPropertyType = "string";
        }
        else if (pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(bool?))
        {
            currentPropertyType = "bool";
        }
        else if (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
        {
            currentPropertyType = "DateTime";
        }

        // **view the next section...**
    }
}

To get the generic type definition of the property type and compare it with List<>获取属性类型的泛型类型定义并与List<>进行比较

// If the Type is List<T>
// To check if the type of the property is List<>, we have to first get its
// generic type definition then we can compare it with List<>. 
// If we get null (maybe because we have not a generic type) we avoid the 
// comparison with List<> and the condition is false. If we get it, 
// we compare and if the types match, we can call GetData on the list's items.
if (GetGenericTypeDefinition(pi.PropertyType)?.Equals(typeof(List<>)) ?? false)
{
    Type itemType = pi.PropertyType.GetGenericArguments()[0];
    var myListObject = (IEnumerable<object>)pi.GetValue(myObject);

    foreach (var item in myListObject)
    {
        GetData(item);
    }              
}

This is the implementation of the method GetGenericTypeDefinition这是方法 GetGenericTypeDefinition 的实现

static Type GetGenericTypeDefinition(Type type)
{
    // If type is not a generic type we can't get its generic definition so we return null
    if (!type.IsGenericType)
        return null;

    return type.GetGenericTypeDefinition();
}

I've included a little Main method to test my implementation easily.我包含了一些 Main 方法来轻松测试我的实现。

class Class1
{
    public int Val { get; set; }

    public List<Class2> Items { get; set; }
}

class Class2
{
    public int Val1 { get; set; }
    public int Val2 { get; set; }
}

static void Main(string[] args)
{
    Class1 obj = new Class1
    {
        Val = 2,
        Items = new List<Class2>
        {
            new Class2
            {
                Val1 = 15,
                Val2 = 22
            },
            new Class2
            {
                Val1 = 107,
                Val2 = 87
            },
            new Class2
            {
                Val1 = 44,
                Val2 = 18
            }
        }

    };

    GetData(obj);

    Console.ReadKey();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM