673 Stimmen

Alle Typen ermitteln, die eine Schnittstelle implementieren

Wie kann ich unter Verwendung von Reflection alle Typen, die eine Schnittstelle implementieren, mit C# 3.0/.NET 3.5 mit so wenig Code wie möglich abrufen und Iterationen minimieren?

Das möchte ich neu schreiben:

foreach (Type t in this.GetType().Assembly.GetTypes())
    if (t is IMyInterface)
        ; //do stuff

19voto

Lasse V. Karlsen Punkte 364542

Schleife durch alle geladenen Assemblies, Schleife durch alle ihre Typen, und prüfen, ob sie die Schnittstelle implementieren.

etwas wie:

Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
    foreach (Type t in asm.GetTypes()) {
        if (ti.IsAssignableFrom(t)) {
            // here's your type in t
        }
    }
}

12voto

Carl Nayak Punkte 91

Das hat bei mir funktioniert (wenn Sie möchten, können Sie Systemtypen bei der Suche ausschließen):

Type lookupType = typeof (IMenuItem);
IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where(
        t => lookupType.IsAssignableFrom(t) && !t.IsInterface);

12voto

Antonin GAVREL Punkte 7751

Andere Antworten arbeiteten nicht mit einer generische Schnittstelle .

Diese hier tut es, ersetzen Sie einfach typeof(ISomeInterface) durch typeof (T).

List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
            .Where(x => typeof(ISomeInterface).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
            .Select(x => x.Name).ToList();

Also mit

AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())

erhalten wir alle Baugruppen

!x.IsInterface && !x.IsAbstract

wird verwendet, um die Schnittstelle und die abstrakten auszuschließen und

.Select(x => x.Name).ToList();

um sie in einer Liste zu haben.

9voto

rvnlord Punkte 3048

Ich sehe hier so viele überkomplizierte Antworten, und die Leute sagen mir immer, dass ich dazu neige, die Dinge zu sehr zu verkomplizieren. Auch mit IsAssignableFrom Methode zur Lösung des OP-Problems ist falsch!

Hier ist mein Beispiel, es wählt alle Baugruppen aus der App-Domäne, dann nimmt es flache Liste aller verfügbaren Typen und überprüft jeden einzelnen Typs Liste der Schnittstellen für Übereinstimmung:

public static IEnumerable<Type> GetImplementingTypes(this Type itype) 
    => AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
           .Where(t => t.GetInterfaces().Contains(itype));

6voto

chtenb Punkte 13189

Alle bisher veröffentlichten Antworten berücksichtigen entweder zu wenige oder zu viele Baugruppen. Sie müssen nur die Baugruppen prüfen, die auf die Baugruppe verweisen, die die Schnittstelle enthält. Dies minimiert die Anzahl der statischen Konstruktoren, die unnötigerweise ausgeführt werden, und spart eine Menge Zeit und möglicherweise unerwartete Seiteneffekte im Falle von Assemblies von Drittanbietern.

public static class ReflectionUtils
{
    public static bool DoesTypeSupportInterface(Type type, Type inter)
    {
        if (inter.IsAssignableFrom(type))
            return true;
        if (type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == inter))
            return true;
        return false;
    }

    public static IEnumerable<Assembly> GetReferencingAssemblies(Assembly assembly)
    {
        return AppDomain
            .CurrentDomain
            .GetAssemblies().Where(asm => asm.GetReferencedAssemblies().Any(asmName => AssemblyName.ReferenceMatchesDefinition(asmName, assembly.GetName())));
    }

    public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
    {
        var assembliesToSearch = new Assembly[] { desiredType.Assembly }
            .Concat(GetReferencingAssemblies(desiredType.Assembly));
        return assembliesToSearch.SelectMany(assembly => assembly.GetTypes())
            .Where(type => DoesTypeSupportInterface(type, desiredType));
    }

    public static IEnumerable<Type> NonAbstractTypesImplementingInterface(Type desiredType)
    {
        return TypesImplementingInterface(desiredType).Where(t => !t.IsAbstract);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X