Cómo encontrar todos los tipos en un ensamblado que heredan de un tipo específico C #

92

¿Cómo se obtiene una colección de todos los tipos que heredan de otro tipo específico?

aceinthehole
fuente

Respuestas:

150

Algo como:

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

Si necesita manejar genéricos, eso se vuelve algo más complicado (por ejemplo, pasar el List<>tipo abierto pero esperar obtener un tipo derivado de List<int>). De lo contrario, es simple aunque :)

Si desea excluir el tipo en sí, puede hacerlo con bastante facilidad:

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

Tenga en cuenta que esto también le permitirá especificar una interfaz y encontrar todos los tipos que la implementan, en lugar de simplemente trabajar con clases como lo Type.IsSubclassOfhace.

Jon Skeet
fuente
2
¡Gracias! Terminé usando esto Gracias - Terminé usando esta lista pública estática <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Donde (tipo => tipo.IsSubclassOf (baseType)). Listar(); }
aceinthehole
@Downvoter aquí. Mi comentario desapareció. Como lo indica aceinthehole, la respuesta es incorrecta. Agregué la respuesta correcta porque me perdí el comentario de ases hasta que encontré que el código no funcionaba. Feliz Navidad.
Tim Murphy
@Tim: No es incorrecto, es un poco diferente. IsAssignableFromdebería funcionar también. En particular, mi versión también se adapta a las interfaces. ¿Probaste mi código? ¿En qué caso falla mi respuesta?
Jon Skeet
1
@Jon. Muy bien, su método maneja interfaces. Soy programador de VB, heredamos clases e implementamos interfaces. ¿Es esto diferente en C #? Pregunto porque la pregunta, como requería, quiere tipos que hereden un tipo y no implementen un tipo.
Tim Murphy
2
@Tim: En C # solo usamos ":" para ambos ... pero generalmente consideraría las interfaces como parte de la jerarquía de herencia de un tipo.
Jon Skeet
27

El siguiente método obtendrá una colección de tipos que heredan un 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

Si necesita incluir tipos que implementan una interfaz, consulte la respuesta de @Jon Skeet.

Tim Murphy
fuente
1

Tienes que enumerar todos los tipos y comprobar cada uno si hereda el que estás buscando.

Algún código como el de esta pregunta puede resultarle útil.

Thomas Danecker
fuente
1

Considere usar este método (escrito para una 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
fuente