注入一个包含所有已注册接口实现的可枚举对象

7

给定以下接口:

public interface IMyProcessor
{
    void Process();
}

我希望能够注册多个实现,并且让我的DI容器将它们注入到类中的可枚举对象中,就像这样:
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();
        }
    }
 }

这是否可行? 我当前实现的 MyProcessorLibrary 通过静态查找所有的 IMyProcessor 实现,但如果可以的话,我更愿意通过容器来完成。 我正在使用 Unity,但很想知道其他容器是否支持它。
编辑:感谢迄今为止的回答。 清楚地说,我想将 MyProcessorLibrary 注入另一个类中,并将其构建为依赖对象树的布线的一部分,例如:
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
可能是解决使用Unity解析IEnumerable<T>的问题的重复内容。 - Mark Seemann
4个回答

4
是的,这是可行的。您需要为通过接口注册的类型赋予 “字符串名称”。使用没有字符串名称的 Register 仍然会分配一个名称(据我所记是“默认值”),它在您调用 Resolve<T> 时解析,但是在您调用 ResolveAll<T> 时不解析。因此,您可能需要给所有处理器命名。
来自 msdn 的示例(适应)。
// 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();

非常感谢 - 我觉得我的问题表述不够清楚。我已经更新了它。 - Steve Wilkes

3

我不了解Unity,无法对其进行评价,但是使用Ninject(请参见多重注入),这是完全可行的,而我就在使用它。


太棒了,这正是我想做的...如果在Unity中没有找到任何东西,我会稍后接受这个答案。谢谢! :) - Steve Wilkes

2

这是来自微软Unity 2.0文档。请检查您使用的版本。对于其他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>();

编辑:

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

非常感谢您的帮助 - 我觉得我在问题描述上还不够清晰。我已经更新了它。 - Steve Wilkes

0

它完全支持MEF。

您需要导出所有实现此接口的类,然后使用[ImportMany]。

例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接