2012-03-07 2 views
5

Data la seguente interfaccia:Iniettando un Enumerable contenente tutte le implementazioni registrati di un'interfaccia

public interface IMyProcessor 
{ 
    void Process(); 
} 

mi piacerebbe essere in grado di registrare più implementazioni e avere il mio contenitore DI iniettare un enumerabile di loro in una classe come this:

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

È possibile? La mia attuale implementazione di MyProcessorLibrary ricerca tutte le implementazioni IMyProcessor staticamente, ma preferirei farlo attraverso un contenitore se posso. Sto usando Unity, ma sono curioso di sapere se altri contenitori lo supportano.

Edit:

Grazie per le risposte finora; per essere chiari, voglio iniettare MyProcessorLibrary in un'altra classe e farlo costruire come parte del cablaggio di un albero di oggetti dipendenti, ad es.

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

possibile duplicato di [Risoluzione IEnumerable con Unity] (http: // stackoverflow.com/questions/1961549/resolving-ienumerablet-with-unity) –

risposta

1

Non posso parlare per l'Unità come io non lo uso, ma è sicuramente possibile con Ninject (vedi Multi Injection) che io faccio uso.

+0

Fantastico, questo è esattamente ciò che voglio fare ... se non succede niente per Unity, accetto questa risposta tra un po '. Grazie! :) –

4

Sì, è possibile farlo. Tutto ciò che serve è dare i nomi di stringa ai tipi che si stanno registrando con l'interfaccia. Register senza un nome di stringa assignes ancora un nome (per quanto mi ricordo è "Default") internamente, viene risolto quando si chiama Resolve<T>, ma non viene risolto quando si chiama ResolveAll<T>. Quindi potrebbe essere necessario dare alcuni nomi ai processori.

Un campione da msdn (adattato):

// 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

Grazie mille per questo - non penso di essere stato abbastanza chiaro nella mia domanda. L'ho aggiornato. –

1

Questo da Microsoft Unità documentazione 2.0. Controlla la versione che usi. Non sono sicuro per gli altri 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

Grazie mille per questo - non penso di essere stato abbastanza chiaro nella mia domanda. L'ho aggiornato. –

0

È completamente supportato con MEF.

Avresti per esportare tutte le classi che implementano questa interfaccia, quindi utilizzare [ImportMany]

Esempio:

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