查找泛型类的所有派生类型

本文关键字:派生 类型 泛型类 查找 | 更新日期: 2023-09-27 18:05:19

我有一个泛型类和一个派生类如下。

public class GenericClass<T> { ... }
public class DerivedClass : GenericClass<SomeType> { ... }

如何通过反射找到派生类?我试过下面两种方法,但似乎都不起作用。

System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(GenericClass<>).IsAssignableFrom(t));
System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(GenericClass<>));

查找泛型类的所有派生类型

var result = System.Reflection.Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => t.BaseType != null && t.BaseType.IsGenericType && 
                t.BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>));

实际情况要复杂一些。t. basetype可能返回null(例如当t是一个接口时)。还要注意类型。IsSubclassOf方法对泛型类型不起作用!如果处理的是泛型类型,则应该使用GetTypeDefinition方法。我最近写了一篇关于如何获得类的所有派生类型的博文。下面是一个适用于泛型的IsSubclass方法:

public static bool IsSubclassOf(Type type, Type baseType)
{
    if (type == null || baseType == null || type == baseType)
        return false;
    if (baseType.IsGenericType == false)
    {
        if (type.IsGenericType == false)
            return type.IsSubclassOf(baseType);
    }
    else
    {
        baseType = baseType.GetGenericTypeDefinition();
    }
    type = type.BaseType;
    Type objectType = typeof(object);
    while (type != objectType && type != null)
    {
        Type curentType = type.IsGenericType ?
            type.GetGenericTypeDefinition() : type;
        if (curentType == baseType)
            return true;
        type = type.BaseType;
     }
    return false;
}

因为我需要递归地找到所有的派生类型,所以我编写了这段代码,并将与任何可能需要它的人分享:

    public void ListAllDerviedTypes()
    {
        Type entityType = typeof(TableAdapter);
        Assembly assembly = Assembly.LoadFrom(entityType.Assembly.Location);
        Type[] types = assembly.GetTypes();
        List<Type> results = new List<Type>();
        GetAllDerivedTypesRecursively(types, typeof(SiteAndSectorsTable<>), ref results);
        foreach (var type in results)
        {
            Console.WriteLine(type.Name);
        }
    }
    private static void GetAllDerivedTypesRecursively(Type[] types, Type type1, ref List<Type> results)
    {
        if (type1.IsGenericType)
        {
            GetDerivedFromGeneric(types, type1, ref results);
        }
        else
        {
            GetDerivedFromNonGeneric(types, type1, ref results);
        }
    }
    private static void GetDerivedFromGeneric(Type[] types, Type type, ref List<Type> results)
    {
        var derivedTypes = types
            .Where(t => t.BaseType != null && t.BaseType.IsGenericType &&
                        t.BaseType.GetGenericTypeDefinition() == type).ToList();
        results.AddRange(derivedTypes);
        foreach (Type derivedType in derivedTypes)
        {
            GetAllDerivedTypesRecursively(types, derivedType, ref results);
        }
    }

    public static void GetDerivedFromNonGeneric(Type[] types, Type type, ref List<Type> results)
    {
        var derivedTypes = types.Where(t => t != type && type.IsAssignableFrom(t)).ToList();
        results.AddRange(derivedTypes);
        foreach (Type derivedType in derivedTypes)
        {
            GetAllDerivedTypesRecursively(types, derivedType, ref results);
        }
    } 

Kim回答的改进版(更短):

    public List<Type> GetAllDerivedTypes(Type baseType)
    {
        Assembly assembly = Assembly.LoadFrom(baseType.Assembly.Location);
        Type[] typesInAssembly = assembly.GetTypes();
        var results = new List<Type>();
        GetAllDerivedTypesRecursively(typesInAssembly, baseType, ref results);
        return results;
    }
    private static void GetAllDerivedTypesRecursively(Type[] types, Type baseType, ref List<Type> results)
    {
        Type[] derivedTypes;
        if (baseType.IsGenericType)
            derivedTypes = types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == baseType).ToArray();
        else
            derivedTypes = types.Where(t => t != baseType && baseType.IsAssignableFrom(t)).ToArray();
        results.AddRange(derivedTypes);
        foreach (Type derivedType in derivedTypes)
            GetAllDerivedTypesRecursively(types, derivedType, ref results);
    }