2009-03-31 15 views
65

In un determinato spazio dei nomi, ho un set di classi che implementano un'interfaccia. Chiamiamolo ISomething. Ho un'altra classe (chiamiamola CClass) che sa di ISomething ma non conosce le classi che implementano quell'interfaccia.Come trovare tutte le classi che implementano una determinata interfaccia?

Mi piacerebbe che CClass cerchi tutta l'implementazione di ISomething, istanzia un'istanza di esso ed esegui il metodo.

Qualcuno ha un'idea su come farlo con C# 3.5?

+2

possibile duplicato di [Ottenere tutti i tipi che implementano un'interfaccia con C# 3.0] (http://stackoverflow.com/questions/26733/getting-all -types-that-implement-an-interface-with-c-sharp-3-0) –

risposta

127

Un lavoro Codice-campione:

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 
} 

Modifica Aggiunto un controllo per un costruttore senza parametri in modo che la chiamata a CreateInstance avrà successo.

+9

Piccolo suggerimento per la pulizia - utilizzare Type.EmptyTypes invece di creare un'istanza di una nuova matrice di tipo vuota. –

+0

C'è un modo per farlo su tutti gli assembly caricati? – gregmac

+13

Nevermind .. istanze var = dal montaggio in AppDomain.CurrentDomain.GetAssemblies() da t in assembly.GetTypes() dove t.GetInterfaces(). Contiene (typeof (ISomething)) && t.GetConstructor (Type .EmptyTypes)! = Null selezionare Activator.CreateInstance (t) come ISomething; – gregmac

8

Un esempio utilizzando Linq:

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

si potrebbe usare qualcosa di simile a quanto segue e adattarlo alle proprie esigenze.

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(); 
    } 
} 

Questo codice potrebbe utilizzare alcuni miglioramenti delle prestazioni, ma è un inizio.

9

È possibile ottenere un elenco di assembly caricati utilizzando questo:

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

Da lì, è possibile ottenere un elenco dei tipi nel montaggio (assumendo tipi pubblici):

Type[] types = assembly.GetExportedTypes(); 

Poi puoi chiedere a ciascun tipo se supporta tale interfaccia trovando quell'interfaccia sull'oggetto:

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

Non sono sicuro se c'è un modo più efficiente per farlo con la riflessione.

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

Forse dovremmo andare in questo modo

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