C# 反射、循环抛出类层次结构并按类型查找字段

C# 反射、循环抛出类层次结构并按类型查找字段,c#,reflection,C#,Reflection,我有一个大的层次结构类,我想循环它的所有属性和子属性等 范例 public class RootClass { // properties .. List<Item> FirstItemsList { get; set;} List<Item> SecondItemsList { get; set;} SubClass SubClass { get; set;} } public class SubClass { // properties

我有一个大的层次结构类,我想循环它的所有属性和子属性等

范例

public class RootClass
{
   // properties ..
   List<Item> FirstItemsList { get; set;}
   List<Item> SecondItemsList { get; set;}
   SubClass SubClass { get; set;}
}
public class SubClass
{
   // properties ..
   List<Item> ThirdItemsList { get; set;}
}
public class Item
{
   //properties 
}
公共类根类
{
//属性。。
List FirstItemsList{get;set;}
List SecondItemsList{get;set;}
子类子类{get;set;}
}
公共类子类
{
//属性。。
List ThirdItemsList{get;set;}
}
公共类项目
{
//性质
}
我想要一个函数,它将返回我找到的所有项目类型的列表 i、 e

public IList GetAllItemsInClass(RootClass实体);

谢谢

如果您需要在一般情况下(任何类层次结构)工作的东西,那么您可以执行以下操作:

您将需要一个递归算法(函数)。该算法将循环遍历成员,将其类型添加到列表中(如果尚未添加),然后返回该列表,并结合刚刚添加到列表中的类型的成员类型,在此进行递归调用。终止条件为:

  • 成员的类型是基元(要检查此项,请使用
    type.IsPrimitive
  • 正在反映的类型在另一个程序集中定义。您可以使用
    Type.assembly
    检查定义程序集
  • 如果需要更简单的方法,那么使用上面的技术,但只需在循环中使用If语句

    告诉我这是否是您想要的,然后我会在有更多时间时为您发布代码示例。

    更新:以下是一个代码示例,展示了如何处理类型并递归获取其中包含的所有类型。您可以这样调用它:
    List typesHere=GetTypes(myObject.GetType())

    公共静态列表GetTypes(类型t)
    {
    列表=新列表();
    if(t.IsPrimitive)
    {
    如果(!list.Contains(t))
    列表。添加(t);
    退货清单;
    }
    如果(!t.Assembly.Equals(System.Reflection.Assembly.getExecutionGassembly()),则为else
    {
    //如果该类型是在另一个程序集中定义的,那么我们将检查其
    //泛型参数。这将处理列表大小写。
    var genArgs=t.GetGenericArguments();
    如果(genArgs!=null)
    foreach(genArgs中的genericArgumentType类型)
    {
    如果(!list.Contains(genericArgumentType))
    AddRange(GetTypes(genericalargumentType));
    }
    退货清单;
    }
    其他的
    {
    //获取道具类型和gen参数
    var types=t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    types.AddRange(t.GetGenericArguments());
    foreach(类型中的System.Type innerType)
    {
    //获取由属性表示的对象以遍历其中的类型。
    如果(!list.Contains(innerType))
    list.Add(innerType);
    else continue;//因为类型已经被添加,因此它的子类型也已经被添加。
    var innerTypes=GetTypes(innerType);
    //添加筛选重复项的类型
    foreach(innerTypes中的t1类型)//list.AddRange(innerTypes);//不过滤重复项。
    如果(!list.Contains(t1))
    列表。添加(t1);
    }
    退货清单;
    }
    }
    
    因此,当我对您在原始帖子中发布的类(具有如下两个基本属性的项)运行此命令时,我得到了以下列表:

    GetTypes(typeof(List<Item>))
    Count = 3
        [0]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
        [1]: {Name = "String" FullName = "System.String"}
        [2]: {Name = "Int32" FullName = "System.Int32"}
    
    GetTypes(typeof(Item))
    Count = 2
        [0]: {Name = "String" FullName = "System.String"}
        [1]: {Name = "Int32" FullName = "System.Int32"}
    
    Reflection.GetTypes(typeof(RootClass))
    Count = 5
        [0]: {Name = "List`1" FullName = "System.Collections.Generic.List`1[[AssemblyNameXYZ.Item, AssemblyNameXYZ, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
        [1]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
        [2]: {Name = "String" FullName = "System.String"}
        [3]: {Name = "Int32" FullName = "System.Int32"}
        [4]: {Name = "SubClass" FullName = "AssemblyNameXYZ.SubClass"}
    
    GetTypes(typeof(List))
    计数=3
    [0]:{Name=“Item”FullName=“AssemblyNameXYZ.Item”}
    [1] :{Name=“String”FullName=“System.String”}
    [2] :{Name=“Int32”FullName=“System.Int32”}
    GetTypes(typeof(Item))
    计数=2
    [0]:{Name=“String”FullName=“System.String”}
    [1] :{Name=“Int32”FullName=“System.Int32”}
    Reflection.GetTypes(typeof(RootClass))
    计数=5
    [0]:{Name=“List`1”FullName=“System.Collections.Generic.List`1[[AssemblyNameXYZ.Item,AssemblyNameXYZ,Version=1.0.0,Culture=neutral,PublicKeyToken=null]}
    [1] :{Name=“Item”FullName=“AssemblyNameXYZ.Item”}
    [2] :{Name=“String”FullName=“System.String”}
    [3] :{Name=“Int32”FullName=“System.Int32”}
    [4] :{Name=“SubClass”FullName=“AssemblyNameXYZ.SubClass”}
    

    我没有做过全面的测试,但这至少应该为你指明了正确的方向。有趣的问题。我的回答很有趣。

    可能重复我试图使用此代码,但不知道如何修改it@ibm123-你能提供一个你期望看到的输出的例子吗?使用反射获取任何特定类的属性(以及由其属性表示的任何类的属性)都很简单,但是如果不查看您希望如何报告它们,就很难回答。我现在有一个考试。之后,我将更有动力发布一个代码示例!3-4小时后见:)
        public static List<Type> GetTypes(Type t)
        {
            List<Type> list = new List<Type>();
            if (t.IsPrimitive)
            {
                if (!list.Contains(t))
                    list.Add(t);
                return list;
            }
            else if (!t.Assembly.Equals(System.Reflection.Assembly.GetExecutingAssembly()))
            {
                //if the type is defined in another assembly then we will check its
                //generic parameters. This handles the List<Item> case.
                var genArgs = t.GetGenericArguments();
                if (genArgs != null)
                    foreach (Type genericArgumentType in genArgs)
                    {
                        if(!list.Contains(genericArgumentType))
                            list.AddRange(GetTypes(genericArgumentType));
                    }
                return list;
            }
            else
            {
                //get types of props and gen args
                var types = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Select(pi => pi.PropertyType).ToList();
                types.AddRange(t.GetGenericArguments());
                foreach (System.Type innerType in types)
                {
                    //get the object represented by the property to traverse the types in it.
                    if (!list.Contains(innerType))
                        list.Add(innerType);
                    else continue; //because the type has been already added and as thus its child types also has been already added.
    
                    var innerInnerTypes = GetTypes(innerType);
                    //add the types filtering duplicates
                    foreach (Type t1 in innerInnerTypes) //list.AddRange(innerTypes); //without filtering duplicates.
                        if (!list.Contains(t1))
                            list.Add(t1);
                }
                return list;
            }
        }
    
    GetTypes(typeof(List<Item>))
    Count = 3
        [0]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
        [1]: {Name = "String" FullName = "System.String"}
        [2]: {Name = "Int32" FullName = "System.Int32"}
    
    GetTypes(typeof(Item))
    Count = 2
        [0]: {Name = "String" FullName = "System.String"}
        [1]: {Name = "Int32" FullName = "System.Int32"}
    
    Reflection.GetTypes(typeof(RootClass))
    Count = 5
        [0]: {Name = "List`1" FullName = "System.Collections.Generic.List`1[[AssemblyNameXYZ.Item, AssemblyNameXYZ, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
        [1]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
        [2]: {Name = "String" FullName = "System.String"}
        [3]: {Name = "Int32" FullName = "System.Int32"}
        [4]: {Name = "SubClass" FullName = "AssemblyNameXYZ.SubClass"}