获取泛型类的子类型列表
本文关键字:类型 列表 泛型类 获取 | 更新日期: 2023-09-27 18:12:56
我有一个具有许多子类型的泛型类:
public abstract class MyClass<T> : MyBaseClass where T : class
{...}
public class MySubClassA : MyClass<A>
{...}
public class MySubClassB : MyClass<B>
{...}
是否有一种简单的方法来搜索MyClass的子类并获得包含MySubClassA和MySubClassB的IEnumerable<Type>
?
我以前使用过这个方法,但我不确定如何适应它用于泛型:
public static IEnumerable<Type> GetSubTypesOf(Type t, bool baseAssemblyOnly = false)
{
List<Type> types = new List<Type>();
Assembly[] searchAssemblies = baseAssemblyOnly
? new[] { Assembly.GetAssembly(t) }
: AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly a in searchAssemblies)
{
types.AddRange(a.GetTypes()
.Where(myType => myType.IsClass
&& !myType.IsAbstract
&& myType.IsSubclassOf(t)));
}
return types;
}
这有点复杂,因为您必须搜索类型的基本类型才能找到与MyClass<>
的开放泛型类型定义匹配的类型。您可以定义两个帮助器方法:
public static IEnumerable<Type> BaseTypesOf(Type t)
{
while (t != null)
{
yield return t;
t = t.BaseType;
}
}
public static Type FindGenericBaseTypeOf(Type t, Type openType)
{
return BaseTypesOf(t)
.FirstOrDefault(bt => bt.IsGenericType && bt.GetGenericTypeDefinition() == openType);
}
则可以将它们应用到输入的类型序列中进行搜索,例如
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.IsClass && !t.IsAbstract)
.Select(t => new { Type = t, GenericBase = FindGenericBaseTypeOf(t, typeof(MyClass<>)) })
.Where(ts => ts.GenericBase != null)
.Select(ts => ts.GenericBase.GetGenericArguments().First())
.ToArray();
问题是,当您为t
参数传递typeof(MyClass<>)
时,您不是传递实例化的泛型类型,而是传递泛型类型定义。这意味着您的所有类都不会响应IsSubclassOf(t)
。
你可以这样修改代码:
List<Type> types = searchAssemblies
.SelectMany(a =>
a.GetTypes()
.Where(myType => myType.IsClass && !myType.IsAbstract && HasGenericBase(myType, t))
).ToList();
...
private static bool HasGenericBase(Type myType, Type t) {
Debug.Assert(t.IsGenericTypeDefinition);
while (myType != typeof(object)) {
if (myType.IsGenericType && myType.GetGenericTypeDefinition() == t) {
return true;
}
myType = myType.BaseType;
}
return false;
}