如果您需要可以在一般情况下工作的东西(任何类层次结构),那么您可以执行以下操作:
您将需要一个递归算法(函数)。该算法将遍历成员,将它们的类型添加到列表中(如果它们尚未添加),然后返回该列表,结合刚刚添加到列表中的类型的成员的类型 - 在这里您进行递归称呼。终止条件是:
- 成员的类型是原始类型(使用
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"}
我没有进行全面的测试,但这至少应该为您指明正确的方向。有趣的问题。我很乐意回答。