2012-03-07 18 views
5

Dada la siguiente interfaz:la inyección de un Enumerable que contiene todas las implementaciones registradas de una interfaz

public interface IMyProcessor 
{ 
    void Process(); 
} 

Me gustaría ser capaz de registrar varias implementaciones y tienen mi contenedor DI inyectar un enumerable de ellos en una clase como esto:

public class MyProcessorLibrary 
{ 
    private readonly IMyProcessor[] _processors; 

    public MyProcessingThing(IMyProcessor[] processors) 
    { 
     this._processors = processors; 
    } 

    public void ProcessAll() 
    { 
     foreach (var processor in this._processors) 
     { 
      processor.Process(); 
     } 
    } 
} 

¿Esto es posible? Mi implementación actual de MyProcessorLibrary busca todas las implementaciones IMyProcessor estáticamente, pero prefiero hacerlo a través de un contenedor si puedo. Estoy usando Unity, pero tengo curiosidad si otros contenedores lo soportan.

Editar:

Gracias por las respuestas hasta el momento; para ser claro, quiero inyectar MyProcessorLibrary en otra clase, y hacer que se construya como parte del cableado de un árbol de objetos dependientes, p.

public class MyProcessorRepository 
{ 
    public MyProcessorRepository(MyProcessorLibrary processorLibrary) 
    { 
    } 
} 

public class MyProcessorService 
{ 
    public MyProcessorService(MyProcessorRepository processorRepository) 
    { 
    } 
} 

var container = new UnityContainer(); 
// Register a bunch of IMyProcessors... 

var service = container.Resolve<MyProcessorService>(); 
+1

posible duplicado de [Resolución de IEnumerable con Unity] (http: // stackoverflow.com/questions/1961549/resolving-ienumerablet-with-unity) –

Respuesta

1

No puedo hablar por la Unidad como yo no lo uso, pero es definitivamente posible con Ninject (ver Multi Injection), que yo utilizo.

+0

Impresionante, eso es exactamente lo que quiero hacer ... si no aparece nada para la Unidad, aceptaré esta respuesta en un momento. ¡Gracias! :) –

4

Sí, es posible hacer esto. Todo lo que necesita es dar nombres de cadena a los tipos que está registrando con la interfaz. Register sin un nombre de cadena todavía assignes un nombre (por lo que yo recuerdo es "por defecto") internamente, se resuelve cuando se llama Resolve<T>, pero no se resuelve cuando se llama ResolveAll<T>. Por lo tanto, es posible que deba darle algunos nombres a todos sus procesadores.

una muestra de msdn (adaptado):

// Create container and register types using a name for each one 
IUnityContainer myContainer = new UnityContainer(); 
myContainer.RegisterType<IMyProcessor, MyProcessorA>(); //default 
myContainer.RegisterType<IMyProcessor, MyProcessorB>("MyProcessorB"); 
myContainer.RegisterType<IMyProcessor, MyProcessorC>("MyProcessorC"); 

// Retrieve a list of non-default types registered for IMyProcessor 
// List will only contain the types MyProcessorB and MyProcessorC 
IEnumerable<IMyProcessor> serviceList = myContainer.ResolveAll<IMyProcessor>(); 

//usage 
var library = new MyProcessorLibrary(serviceList); 
library.ProcessAll(); 
+0

Muchas gracias por esto, no creo que haya sido lo suficientemente claro en mi pregunta. Lo he actualizado –

1

Esto es de Microsoft Unidad documentación 2.0. Mira la versión que usas. No estoy seguro para otros IoC.

// Create container and register types using a name for each one 
IUnityContainer myContainer = new UnityContainer(); 
myContainer.RegisterType<IMyProcessor, MyProcessor1>(); 
myContainer.RegisterType<IMyProcessor, MyProcessor2>("number2"); 

// Retrieve a list of non-default types registered for IMyService 
IEnumerable<IMyProcessor> processors = myContainer.ResolveAll<IMyService>(); 

EDIT:

// update MyProcessorLibrary with this property 
[Dependency] 
public IEnumerable<IMyProcessor> MyProcessingThing 
{ 
get { return _processors; } 
set { _processors = value; } 
} 

//then inject the library class like this 
var lib = myContainer.Resolve<MyProcessorLibrary>(); 
myProcessorRepository(lib) 
+0

Muchas gracias por esto, no creo que haya sido lo suficientemente claro en mi pregunta. Lo he actualizado –

0

Es totalmente compatible con MEF.

Habría que exportar todas las clases que implementan esta interfaz, a continuación, utilice [ImportMany]

Ejemplo:

public interface IMyProcessor { void Process(); } 

[Export(typeof(IMyProcessor)] 
public class FirstProc : IMyProcessor { ... } 

[Export(typeof(IMyProcessor)] 
public class SecondProc : IMyProcessor { ... } 

[Export] 
public class MyTest() 
{ 
    [ImportMany] 
    public IMyProcessor[] MyProcessors { get; set; } 
} 
Cuestiones relacionadas