我有一个大的层次结构类,我想循环所有它的属性和子属性等。
实施例
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
}
我想要一个函数,它会返回一个找到的所有Item类型的列表 即
public IList<Item> GetAllItemsInClass(RootClass entity);
由于
答案 0 :(得分:0)
如果您需要能够在一般情况下工作的东西(任何类层次结构),那么您可以执行以下操作:
您需要一个递归算法(函数)。该算法将循环遍历成员,将其类型添加到列表中(如果它们尚未添加)然后返回该列表,COMBINED与刚添加到列表中的类型成员的类型 - 在此处进行递归呼叫。终止条件是:
Type.IsPrimitive
)。Type.Assembly
。如果你需要更简单的东西,那么使用上面的技术,但只需在循环中使用if语句。
让我知道这是你想要的还是没有,然后我会在你有更多时间的时候为你发布一个代码示例。
更新:以下是一个代码示例,展示了如何处理类型并递归获取其中包含的所有类型。您可以这样称呼它:List typesHere = GetTypes(myObject.GetType())
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"}
我没有进行全面测试,但这至少应该指向正确的方向。有趣的问题。我很开心回答。