2009-03-31 11 views
65

Unter einem bestimmten Namespace habe ich eine Reihe von Klassen, die eine Schnittstelle implementieren. Nennen wir es ISomething. Ich habe eine andere Klasse (nennen wir es CClass), die über ISomething weiß, aber nicht über die Klassen, die diese Schnittstelle implementieren.Wie finden Sie alle Klassen, die eine bestimmte Schnittstelle implementieren?

Ich möchte, dass CClass nach der ganzen Implementierung von ISomething suchen, instanziieren Sie eine Instanz davon und führen Sie die Methode aus.

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

+2

möglich Duplikat [Erste alle Arten, die eine Schnittstelle mit C# 3.0 implementieren] gehen (http://stackoverflow.com/questions/26733/getting-all -types-das-implementieren-eine-Schnittstelle-mit-c-sharp-3-0) –

Antwort

127

Ein Arbeits Code-Beispiel:

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 
} 

bearbeiten Added einen Scheck für einen parameterlosen Konstruktor so dass der Aufruf von CreateInstance gelingen wird.

+9

Tiny Cleanup Vorschlag - verwenden Sie Type.EmptyTypes, anstatt ein neues leeres Type-Array instanziieren. –

+0

Gibt es eine Möglichkeit, dies über alle geladenen Baugruppen hinweg zu tun? – gregmac

+13

vergiss .. var instances = von der Montage in AppDomain.CurrentDomain.GetAssemblies() von t in assembly.GetTypes() wo t.GetInterfaces(). Enthält (typeof (ISomething)) && t.GetConstructor (Typ .EmptyTypes)! = Null Wählen Sie Activator.CreateInstance (t) als ISomething; – gregmac

8

Ein Beispiel unter Verwendung von Linq:

var types = 
    myAssembly.GetTypes() 
      .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null); 
2

Sie so etwas wie die folgenden und sie auf Ihre Bedürfnisse nutzen könnten.

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

9

Sie können eine Liste der geladenen Baugruppen erhalten, indem diese mit:

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

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

Type[] types = assembly.GetExportedTypes(); 

Dann Sie können 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 einen effizienteren Weg gibt, dies mit Reflektion zu tun.

3
foreach (Type t in Assembly.GetCallingAssembly().GetTypes()) 
{ 
    if (t.GetInterface("ITheInterface") != null) 
    { 
     ITheInterface executor = Activator.CreateInstance(t) as ITheInterface; 
     executor.PerformSomething(); 
    } 
} 
0

Vielleicht sollten wir auf diese Weise

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