Как найти все типы в сборке, которые наследуют от определенного типа С#

Как вы получаете коллекцию всех типов, которые наследуются от определенного другого типа?

Ответ 1

Что-то вроде:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}

Если вам нужно обрабатывать дженерики, это становится несколько более сложным (например, передается открытым типом List<>, но ожидает возврата типа, полученного из List<int>). В противном случае это просто, хотя:)

Если вы хотите исключить сам тип, вы можете сделать это достаточно легко:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => t != baseType && 
                                          baseType.IsAssignableFrom(t));
}

Обратите внимание, что это также позволит вам указать интерфейс и найти все типы, которые его реализуют, а не просто работать с классами как Type.IsSubclassOf.

Ответ 2

Следующий метод получит набор типов, которые наследуют тип.

С#

public IEnumerable<Type> FindSubClassesOf<TBaseType>()
{   
    var baseType = typeof(TBaseType);
    var assembly = baseType.Assembly;

    return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
}

VB.NET

Public Function FindSubClasses(Of TBaseType)() As IEnumerable(Of Type)

    Dim baseType = GetType(TBaseType)
    Dim assembly = baseType.Assembly

    Return From t In assembly.GetTypes() 
           Where t.IsSubClassOf(baseType) 
           Select t

End Function

Если вам нужно включить типы, реализующие интерфейс, см. ответ @Jon Skeet.

Ответ 3

Вы должны перечислить все типы и проверить для каждого, если он наследует тот, который вы ищете.

Некоторый код, такой как этот вопрос, может быть вам полезен.

Ответ 4

Рассмотрим использование этого метода (написанного для PCL):

public IEnumerable<Type> FindDerivedTypes( Assembly assembly, Type baseType )
{
        TypeInfo baseTypeInfo = baseType.GetTypeInfo();
        bool isClass = baseTypeInfo.IsClass, isInterface = baseTypeInfo.IsInterface;

        return
            from type in assembly.DefinedTypes
            where isClass ? type.IsSubclassOf( baseType ) :
                  isInterface ? type.ImplementedInterfaces.Contains( baseTypeInfo.AsType() ) : false
            select type.AsType();
}