Como encontrar todos os tipos em um assembly que herdam de um tipo específico C #

92

Como você obtém uma coleção de todos os tipos que herdam de um outro tipo específico?

aceinthehole
fonte

Respostas:

150

Algo como:

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

Se você precisa lidar com genéricos, fica um pouco mais complicado (por exemplo, passar o List<>tipo aberto, mas esperando receber de volta um tipo derivado de List<int>). Caso contrário, é simples :)

Se você deseja excluir o próprio tipo, pode fazer isso com bastante facilidade:

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

Observe que isso também permitirá que você especifique uma interface e encontre todos os tipos que a implementam, em vez de apenas trabalhar com classes como Type.IsSubclassOffaz.

Jon Skeet
fonte
2
Obrigado! Acabei usando este Obrigado - acabei usando este List <Type> público estático GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Onde (type => type.IsSubclassOf (baseType)). Listar(); }
aceinthehole
@Downvoter aqui. Meu comentário desapareceu. Conforme indicado por aceinthehole, a resposta está incorreta. Eu adicionei a resposta correta porque perdi o comentário dos ases até descobrir que o código não funcionava. Feliz Natal.
Tim Murphy
@Tim: Não é incorreto, é um pouco diferente. IsAssignableFromdeve funcionar também. Em particular, minha versão lida com interfaces também. Você testou meu código? Em que caso minha resposta falha?
Jon Skeet
1
@Jon. Muito bem, seu método lida com interfaces. Sou um programador VB, herdamos classes e implementamos interfaces. Isso é diferente em C #? Eu pergunto porque a questão, como solicitei, quer tipos que herdam um tipo e não implementam um tipo.
Tim Murphy
2
@Tim: Em C #, usamos apenas ":" para ambos ... mas geralmente consideraria as interfaces como parte da hierarquia de herança de um tipo.
Jon Skeet
27

O método a seguir obterá uma coleção de tipos que herdam um tipo.

C #

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

Se você precisa incluir tipos que implementam uma interface, veja a resposta de @Jon Skeet.

Tim Murphy
fonte
1

Você tem que enumerar todos os tipos e verificar se cada um herda o que você está procurando.

Algum código como o desta questão pode ser útil para você.

Thomas Danecker
fonte
1

Considere usar este método (escrito para um 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();
}
HappyNomad
fonte