7

Given the following interface:

public interface IMyProcessor
{
    void Process();
}

I'd like to be able to register multiple implementations and have my DI container inject an enumerable of them into a class like 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();
        }
    }
 }

Is this possible? My current implementation of MyProcessorLibrary looks up all the IMyProcessor implementations statically, but I'd rather do it through a container if I can. I'm using Unity, but am curious if other containers support it.

Edit:

Thanks for the answers so far; to be clear I want to inject MyProcessorLibrary into another class, and have it built as part of the wiring up of a tree of dependent objects, e.g.

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>();
Steve Wilkes
  • 7,085
  • 3
  • 29
  • 32
  • 1
    possible duplicate of [Resolving IEnumerable with Unity](http://stackoverflow.com/questions/1961549/resolving-ienumerablet-with-unity) – Mark Seemann Mar 07 '12 at 10:42

4 Answers4

4

Yes, it is possible to do this. All you need, is to give string names to the types you are registering with the interface. Register without a string name still assignes a name (as far as I remember it is "Default") internally, it is resolved when you call Resolve<T>, but it is not resolved when you call ResolveAll<T>. So you may need to give all your processors some names.

A sample from msdn (adapted):

// 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();
oleksii
  • 35,458
  • 16
  • 93
  • 163
3

I can't speak for Unity as I don't use it but it is definitely possible with Ninject (see Multi Injection) which I do use.

Trevor Pilley
  • 16,156
  • 5
  • 44
  • 60
  • Awesome, that's actually exactly what I want to do... if nothing turns up for Unity I'll accept this answer in a bit. Thanks! :) – Steve Wilkes Mar 07 '12 at 10:40
2

This is from Microsoft Unity 2.0 documentation. Check out the version you use. Not sure for others 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)
Arseny
  • 7,251
  • 4
  • 37
  • 52
0

It is fully supported with MEF.

You'd have to Export all the classes that implement this interface, then use [ImportMany]

Example:

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; }
}
Louis Kottmann
  • 16,268
  • 4
  • 64
  • 88