2012-05-24 18 views
8

Tengo un ejemplo:¿Puedo usar Activator.CreateInstance con una interfaz?

 Assembly asm = Assembly.Load("ClassLibrary1"); 
     Type ob = asm.GetType("ClassLibrary1.UserControl1"); 
     UserControl uc = (UserControl)Activator.CreateInstance(ob); 
     grd.Children.Add(uc); 

No estoy creando una instancia de una clase, pero ¿cómo puedo crear una instancia de una clase que implementa alguna de las interfaces? es decir, UserControl1 implementa ILoad interfaz.

U: Puedo transmitir el objeto a la interfaz más tarde, pero no sé qué tipo de ensambles implementa la interfaz.

+6

No se puede crear una instancia de una interfaz; puede crear la clase que implementa la interfaz y pasarla como interfaz. – Marco

+1

No se puede crear una instancia de un objeto del tipo ILoad, es una interfaz. – JustinDanielson

Respuesta

14

Este es un código que he usado varias veces. Se encuentra todo tipo en una asamblea que implementan una determinada interfaz:

Type[] iLoadTypes = (from t in Assembly.Load("ClassLibrary1").GetExportedTypes() 
        where !t.IsInterface && !t.IsAbstract 
        where typeof(ILoad).IsAssignableFrom(t) 
        select t).ToArray(); 

A continuación, tiene todos los tipos de ClassLibrary1 que implementan ILoad.

A continuación, podría crear una instancia todos ellos:

ILoad[] instantiatedTypes = 
    iLoadTypes.Select(t => (ILoad)Activator.CreateInstance(t)).ToArray(); 
+0

Gracias, buena solución. –

+0

Recibo el siguiente error: 'No se pudo encontrar una implementación del patrón de consulta para el tipo de fuente 'System.Reflection.Assembly'. 'Donde' no se encuentra. – dotNET

+1

Lo encontré. 'Load (" ClassLibrary1 ")' en el código anterior debe ir seguido de '.GetExportedTypes();'. – dotNET

4

No puede crear instancia de una interfaz, pero si

UserControl1 implements ILoad inteface

se puede utilizar el objeto resultante como ILoad

ILoad uc = (ILoad)Activator.CreateInstance(ob); 
grd.Children.Add(uc); 

Por otra parte, no es necesario tratarla a través de la interfaz, si se escribe

UserControl1 uc = (UserControl1)Activator.CreateInstance(ob); 
grd.Children.Add(uc); 

miembros de ILoad serían cala ble como uc.SomeILoadMethod();

+0

Siempre que 'ob' sigue siendo un tipo que representa una clase y no una interfaz. – Guillaume

+0

El objeto construido @Guillaume implementa ILoad, por lo que se puede usar directamente – archil

+0

OK, pero ¿cómo puedo encontrar el tipo de ensamblaje, que implementa ** ILoad **? –

3

La interfaz es una interfaz. Es una plantilla. ¿Por qué querrías crear una interfaz? Implementa la interfaz y crea una instancia de esa clase. No se puede crear una instancia de una interfaz, realmente no tiene sentido.

+1

Por supuesto, tiene sentido tener una forma fácil de instanciar una interfaz. Imagina DTOs. POCO sin comportamiento. Desea crearlos como interfaces para usarlos fácilmente en un marco simulado, pero cuando implementa la interfaz, básicamente termina con dos pedazos idénticos de código que necesita mantener. Es por eso que algunos marcos, como NServiceBus, le permite "crear instancias de interfaces". No estoy diciendo que se pueda hacer fácilmente con funciones integradas como el Activador, solo digo que no se puede omitir porque "no tiene sentido" – Morten

4

Lo que desea se puede lograr utilizando un contenedor IoC como `NInject '. Puede configurar un contenedor para devolver un tipo concreto cuando haya solicitado una interfaz.

2

Si se hace referencia a la biblioteca en el proyecto que puede utilizar:

static public IEnumerable<Type> GetTypesFromLibrary<T>(String library) 
    { 
     var MyAsemblies = AppDomain.CurrentDomain.GetAssemblies() 
         .Where(a=>a.GetName().Name.Equals(library)) 
         .Select(a=>a); 
     var Exported = MyAsemblies 
         .FirstOrDefault() 
         .GetExportedTypes(); 
     var Asignable = Exported 
         .Where (t=> !t.IsInterface && !t.IsAbstract 
         && typeof(T).IsAssignableFrom(t)) 
         .Select(t=>t) 
         .AsEnumerable(); 
     return Asignable; 
    } 

    static public T GetInstanceOf<T>(String library, String FullClassName) 
    { 
     Type Type = GetTypesFromLibrary<T>(library) 
         .Where(t => t.FullName.Equals(FullClassName)) 
         .FirstOrDefault(); 
     if (Type != null) 
     { 
      T Instance = (T)Activator.CreateInstance(Type); 
      return Instance; 
     } 
     return default(T); 
    } 
2

El único problema con la respuesta aceptada es que debes tener una clase concreta en su conjunto que implementa la interfaz.

Para evitar que haya creado mi CustomActivator que es capaz de crear un objeto dinámico en tiempo de ejecución y hacer que implemente la interfaz deseada.

lo puse en el GitHub: https://github.com/fabriciorissetto/CustomActivator

La llamada es simple:

CustomActivator.CreateInstance<MyInterface>(); 
Cuestiones relacionadas