structuremap – 同一接口的两个实现

我有一个服务类与以下ctor:

public class (IMessageService emailService, IMessageService smsService) { ... } 

以及IMessageService (电子邮件和短信)的两种实现。 如何配置容器以正确解析此构造函数? 这是命名实例进入的地方,还是另一种情况?

可以使用命名实例或智能实例来解决此问题…

 // Named instances this.For().Use().Named("emailService"); this.For().Use().Named("smsService"); // Smart instances var emailService = this.For().Use(); var smsService = For().Use(); this.For().Use() .Ctor("emailService").Is(emailService) .Ctor("smsService").Is(smsService); 

但我认为你的设计需要一些工作。 您的服务知道电子邮件服务和SMS服务之间的区别是违反Liskov替换原则的事实。 比注入相同类型的2个参数更好的方法是使用复合模式 。

 public class CompositeMessageService : IMessageService { private readonly IMessageService messageServices; public CompositeMessageService(IMessageService[] messageServices) { if (messageServices == null) throw new ArgumentNullException("messageServices"); this.messageServices = messageServices; } public void Send(IMessage message) { foreach (var messageService in this.messageServices) { messageService.Send(message); } } } 

然后,您的原始服务只需要接受单个IMessageService实例。 它不需要知道它正在处理什么类型的IMessageService的细节。

 public SomeService(IMessageService messageService) 

在StructureMap中,您可以轻松注册IMessageService的所有实例,它会自动将它们注入到IMessageService的构造函数参数数组中。

 this.Scan(scan => { scan.TheCallingAssembly(); scan.AssemblyContainingType(); scan.AddAllTypesOf(); }); 

或者您可以显式注入实例。

  this.For().Use() .EnumerableOf().Contains(x => { x.Type(); x.Type(); }); 

这意味着您的配置可以更改为更改首先调用哪个服务的顺序。 根据您当前的设计,这些细节将硬编码到接受2个参数的服务中。

此外,您还可以在不更改设计的情况下添加其他消息服务或删除现有消息服务。

结果命名实例是一种可能的解决方案:

  _.For().Use().Named("emailService"); _.For().Use().Named("smsService"); 
 //First just write below lines in IOC this.For().Use(); this.For().Use(); //Then We can directly use it in our constructor injection of our class //Where we need it IEnumerable messageServices; public ClassNeedsInjection(IEnumerable messageServices) { this.messageServices=messageServices; foreach (var messageService in this.messageServices) { //use both the objects as you wish } } 

不需要复杂。 只需简单地注册接口的所有实现。

  this.For().Use(); this.For().Use(); 

然后,structuremap会自动将IMessageService接口的所有实现注入到具有接口的IEnumerable / list / array的任何构造函数中。 如下所示:

 private IEnumerator _current; public SomeClass(IEnumerable features) { _current = features.GetEnumerator(); } 

希望能帮助到你