2009-03-31 29 views
65

Bajo un espacio de nombres dado, tengo un conjunto de clases que implementan una interfaz. Vamos a llamarlo ISomething. Tengo otra clase (llamémoslo CClass) que conoce aproximadamente ISomething pero no conoce las clases que implementan esa interfaz.¿Cómo encontrar todas las clases que implementan una interfaz determinada?

Me gustaría que CClass busque toda la implementación de ISomething, cree una instancia de la instancia y ejecute el método.

¿Alguien tiene una idea de cómo hacer eso con C# 3.5?

+2

posible duplicado de [Obtener todos los tipos que implementan una interfaz con C# 3.0] (http://stackoverflow.com/questions/26733/getting-all -types-that-implement-an-interface-with-c-sharp-3-0) –

Respuesta

127

un código de muestra de trabajo:

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 
} 

Editar añadido un cheque por un constructor sin parámetros para que la llamada a CreateInstance tendrá éxito.

+9

Sugerencia de limpieza pequeña: use Type.EmptyTypes en lugar de crear una nueva matriz Type vacía. –

+0

¿Hay alguna manera de hacer esto en todos los ensamblajes cargados? – gregmac

+13

no importa .. instancias var = de montaje en AppDomain.CurrentDomain.GetAssemblies() de t en assembly.GetTypes() donde t.GetInterfaces(). Contiene (typeof (ISomething)) && t.GetConstructor (Tipo .EmptyTypes)! = Null seleccione Activator.CreateInstance (t) como ISomething; – gregmac

8

Un ejemplo usando LINQ:

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

usted podría utilizar algo como lo siguiente y adaptarlo a sus necesidades.

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

Este código podría utilizar algunas mejoras de rendimiento, pero es un comienzo.

9

Usted puede obtener una lista de ensamblados cargados mediante el uso de esto:

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

A partir de ahí, se puede obtener una lista de tipos en la asamblea (asumiendo tipos públicos):

Type[] types = assembly.GetExportedTypes(); 

Entonces puede preguntar a cada tipo si es compatible con esa interfaz al encontrar esa interfaz en el objeto:

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

No estoy seguro de si hay una manera más eficiente de hacer esto con la reflexión.

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

Tal vez deberíamos ir por este camino

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