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
检查定义程序集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"}