当需要多个相同类型的实例时,使用Unity进行DI

我需要帮助。 我使用Unity作为我的容器,我想在构造函数中注入两个相同类型的不同实例。

class Example { Example(IQueue receiveQueue, IQueue sendQueue) {} } 

….和IQueue在我的MessageQueue类中实现….

 class MessageQueue : IQueue { MessageQueue(string path) {} } 

如何将两个不同的MessageQueue实例注入我的Example类? 要使用不同路径创建的每个MessageQueue实例。

有很多方法可以达到你想要的结果(由多个答案certificate)。 这是使用命名注册(没有属性)的另一种方式:

 IUnityContainer container = new UnityContainer(); container.RegisterType("ReceiveQueue", new InjectionConstructor("receivePath")); container.RegisterType("SendQueue", new InjectionConstructor("sendPath")); container.RegisterType( new InjectionConstructor( new ResolvedParameter("ReceiveQueue"), new ResolvedParameter("SendQueue"))); Example example = container.Resolve(); 

这种方法的缺点是如果更改了Example构造函数,那么还必须修改注册代码以匹配。 此外,错误将是运行时错误,而不是更优选的编译时错误。

您可以将上述内容与InjectionFactory结合使用,以手动调用构造函数以进行编译时检查:

 IUnityContainer container = new UnityContainer(); container.RegisterType("ReceiveQueue", new InjectionConstructor("receivePath")); container.RegisterType("SendQueue", new InjectionConstructor("sendPath")); container.RegisterType(new InjectionFactory(c => new Example(c.Resolve("ReceiveQueue"), c.Resolve("SendQueue")))); Example example = container.Resolve(); 

如果您使用的是组合根,那么魔术字符串(“ReceiveQueue”和“SendQueue”)的使用将仅限于一个注册位置。

您可以使用名称注册这两个实例:

 myContainer.RegisterInstance("ReceiveQueue", myReceiveMessageQueue); myContainer.RegisterInstance("SendQueue", mySendMessageQueue); 

然后你应该能够按名称解析,但它需要使用Dependency属性:

 class Example { Example([Dependency("ReceiveQueue")] IQueue receiveQueue, [Dependency("SendQueue")] IQueue sendQueue) { } } 

或者注入unity容器然后解析构造函数中的实例:

 class Example { Example(IUnityContainter container) { _receiveQueue = container.Resolve("ReceiveQueue"); _sendQueue = container.Resolve("SendQueue"); } } 

并非所有东西都必须由容器自动连线。 您可以像这样注册Example类:

 container.Register(new InjectionFactory(c => { var receive = new MessageQueue("receivePath"); var send = new MessageQueue("sendPath"); return new Example(receive, send); }); 

好吧,不要

在这种情况下,您应该使用工厂模式。

 class Example { Example(IQueueFactory factory) { _sendQueue = factory.Create("MySend"); _receiveQueue = factory.Create("MyReceive"); } } 

它使意图更加清晰,如果未找到队列或配置不正确,您可以在Example类的内部处理。

我认为之前已经在Stackoverflow上询问过这个问题。 您需要使用ParameterOverride:

ParameterOverride允许您传入构造函数参数的值,以覆盖传递给给定命名构造函数的参数。 仅覆盖参数值,而不是构造函数。

链接到MSDN文章

链接到Stackoverflow文章

 var exampleInstance = new Example(); var queue1 = unityContainer.Resolve(new ParameterOverrides { { "path", "yourPath" }}); var queue2 = unityContainer.Resolve(new ParameterOverrides { { "path", "yourPath2Queue2" }}); exampleInstance.Example(queue1,queue2);