Injecting an Enumerable containing all registered Implementations of an Interface

烂漫一生 提交于 2019-12-07 02:46:31

问题


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

回答1:


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.




回答2:


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



回答3:


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)



回答4:


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


来源:https://stackoverflow.com/questions/9599487/injecting-an-enumerable-containing-all-registered-implementations-of-an-interfac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!