Comment trouver tous les types dans un assembly qui héritent d'un type spécifique C #

92

Comment obtenir une collection de tous les types qui héritent d'un autre type spécifique?

aceinthehole
la source

Réponses:

150

Quelque chose comme:

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

Si vous avez besoin de gérer des génériques, cela devient un peu plus compliqué (par exemple en passant le List<>type ouvert mais en espérant récupérer un type dérivé de List<int>). Sinon c'est simple cependant :)

Si vous souhaitez exclure le type lui-même, vous pouvez le faire assez facilement:

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

Notez que cela vous permettra également de spécifier une interface et de trouver tous les types qui l'implémentent, plutôt que de simplement travailler avec des classes comme le Type.IsSubclassOffait.

Jon Skeet
la source
2
Merci! J'ai fini par utiliser ce Merci - J'ai fini par utiliser cette liste statique publique <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Où (type => type.IsSubclassOf (baseType)). Lister(); }
aceinthehole
@Downvoter ici. Mon commentaire a disparu. Comme indiqué par aceinthehole, la réponse est incorrecte. J'ai ajouté la bonne réponse car j'ai manqué le commentaire d'As jusqu'à ce que je trouve que le code ne fonctionnait pas. Joyeux Noël.
Tim Murphy
@Tim: Ce n'est pas incorrect, c'est légèrement différent. IsAssignableFromdevrait également fonctionner. En particulier, ma version gère également les interfaces. Avez-vous testé mon code? Dans quel cas ma réponse échoue-t-elle?
Jon Skeet
1
@Jon. Tout à fait juste, votre méthode gère les interfaces. Je suis un programmeur VB, nous héritons des classes et implémentons des interfaces. Est-ce différent en C #? Je demande parce que la question, comme je l'ai exigé, veut que les types qui héritent d'un type n'implémentent pas un type.
Tim Murphy
2
@Tim: En C #, nous utilisons simplement ":" pour les deux ... mais je considérerais généralement les interfaces comme faisant partie de la hiérarchie d'héritage d'un type.
Jon Skeet
27

La méthode suivante obtiendra une collection de types qui héritent d'un type.

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 vous devez inclure des types qui implémentent une interface, consultez la réponse de @Jon Skeet.

Tim Murphy
la source
1

Vous devez énumérer tous les types et vérifier pour chacun s'il hérite de celui que vous recherchez.

Certains codes comme celui de cette question peuvent vous être utiles.

Thomas Danecker
la source
1

Pensez à utiliser cette méthode (écrite pour une 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
la source