wake-up-neo.com

Wie finde ich alle Klassen, die eine bestimmte Schnittstelle implementieren?

Unter einem bestimmten Namensraum habe ich eine Reihe von Klassen, die eine Schnittstelle implementieren. Nennen wir es ISomething. Ich habe eine andere Klasse (nennen wir sie CClass), die ISomething kennt, aber nicht weiß, welche Klassen dieses Interface implementieren.

Ich möchte, dass CClass nach der gesamten Implementierung von ISomething sucht, eine Instanz davon instanziiert und die Methode ausführt.

Hat jemand eine Idee, wie das mit C # 3.5 geht?

66
Martin

Eine funktionierende Code-Probe:

var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.GetInterfaces().Contains(typeof(ISomething))
                         && t.GetConstructor(Type.EmptyTypes) != null
                select Activator.CreateInstance(t) as ISomething;

foreach (var instance in instances)
{
    instance.Foo(); // where Foo is a method of ISomething
}

Edit Es wurde eine Überprüfung für einen parameterlosen Konstruktor hinzugefügt, damit der Aufruf von CreateInstance erfolgreich ist.

129
Matt Hamilton

Sie können eine Liste der geladenen Baugruppen erhalten, indem Sie Folgendes verwenden:

Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()

Von dort können Sie eine Liste von Typen in der Assembly abrufen (unter der Annahme, dass öffentliche Typen angenommen werden):

Type[] types = Assembly.GetExportedTypes();

Dann können Sie jeden Typ fragen, ob er diese Schnittstelle unterstützt, indem Sie diese Schnittstelle auf dem Objekt finden:

Type interfaceType = type.GetInterface("ISomething");

Nicht sicher, ob es eine effizientere Möglichkeit gibt, dies durch Reflektion zu erreichen.

10
Mitch Denny

Ein Beispiel mit Linq:

var types =
  myAssembly.GetTypes()
            .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
8
CMS
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
    if (t.GetInterface("ITheInterface") != null)
    {
        ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
        executor.PerformSomething();
    }
}
3
Kiran

Sie könnten etwas wie das Folgende verwenden und es an Ihre Bedürfnisse anpassen. 

var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();

foreach (var type in types)
{
    if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
    {
        ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
        something.TheMethod();
    }
}

Dieser Code könnte einige Leistungsverbesserungen erfordern, aber es ist ein Anfang.

2

Vielleicht sollten wir diesen Weg gehen

foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() ) 
   instance.Execute(); 
0
bane 975