So finden Sie alle Typen in einer Assembly, die von einem bestimmten Typ C # erben

92

Wie erhalten Sie eine Sammlung aller Typen, die von einem bestimmten anderen Typ erben?

aceinthehole
quelle

Antworten:

150

Etwas wie:

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

Wenn Sie mit Generika umgehen müssen, wird dies etwas schwieriger (z. B. Übergabe des offenen List<>Typs, aber Erwartung, einen Typ zurückzugewinnen, der von abgeleitet ist List<int>). Ansonsten ist es aber einfach :)

Wenn Sie den Typ selbst ausschließen möchten, können Sie dies ganz einfach tun:

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

Beachten Sie, dass Sie auf diese Weise auch eine Schnittstelle angeben und alle Typen finden können, die sie implementieren, anstatt wie bisher nur mit Klassen zu arbeiten Type.IsSubclassOf.

Jon Skeet
quelle
2
Vielen Dank! Am Ende habe ich diesen Dank verwendet. Am Ende habe ich diese öffentliche statische Liste <Typ> GetAllSubclassesOf (Typ baseType) {return Assembly.GetAssembly (baseType) .GetTypes () verwendet. Wobei (type => type.IsSubclassOf (baseType)). Auflisten(); }
Aceinthehole
@ Downvoter hier. Mein Kommentar ist verschwunden. Wie durch aceinthehole angezeigt, ist die Antwort falsch. Ich habe die richtige Antwort hinzugefügt, da ich den Kommentar zu Assen verpasst habe, bis ich festgestellt habe, dass der Code nicht funktioniert hat. Fröhliche Weihnachten.
Tim Murphy
@ Tim: Es ist nicht falsch, es ist etwas anders. IsAssignableFromsollte auch funktionieren. Insbesondere kommt meine Version auch mit Schnittstellen zurecht. Hast du meinen Code getestet? In welchem ​​Fall schlägt meine Antwort fehl?
Jon Skeet
1
@ Jon. Ganz richtig, Ihre Methode behandelt Schnittstellen. Ich bin ein VB-Programmierer, wir erben Klassen und implementieren Schnittstellen. Ist das anders in C #? Ich frage, weil die Frage, wie ich es verlangte, Typen möchte, die einen Typ erben, keinen Typ implementieren.
Tim Murphy
2
@Tim: In C # verwenden wir nur ":" für beide ... aber ich würde Schnittstellen im Allgemeinen als Teil der Vererbungshierarchie eines Typs betrachten.
Jon Skeet
27

Die folgende Methode ruft eine Sammlung von Typen ab, die einen Typ erben.

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

Wenn Sie Typen einschließen müssen, die eine Schnittstelle implementieren, lesen Sie die Antwort von @Jon Skeet.

Tim Murphy
quelle
1

Sie müssen alle Typen auflisten und für jeden prüfen, ob er den gesuchten erbt.

Ein Code wie der in dieser Frage kann für Sie nützlich sein.

Thomas Danecker
quelle
1

Erwägen Sie die Verwendung dieser Methode (geschrieben für eine 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
quelle