You could使用命名实例或智能实例来解决这个问题......
// Named instances
this.For<IMessageService>().Use<EmailService>().Named("emailService");
this.For<IMessageService>().Use<SmsService>().Named("smsService");
// Smart instances
var emailService = this.For<IMessageService>().Use<EmailService>();
var smsService = For<IMessageService>().Use<SmsService>();
this.For<ISomeService>().Use<SomeService>()
.Ctor<IMessageService>("emailService").Is(emailService)
.Ctor<IMessageService>("smsService").Is(smsService);
但我认为你的设计需要一些工作。您的服务知道电子邮件服务和 SMS 服务之间的区别,这一事实违反了里氏替换原则。比注入 2 个相同类型的参数更好的方法是使用复合图案 http://sourcemaking.com/design_patterns/composite.
public class CompositeMessageService : IMessageService
{
private readonly IMessageService[] messageServices;
public CompositeMessageService(IMessageService[] messageServices)
{
this.messageServices = messageServices ?? throw new ArgumentNullException(nameof(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<IMessageService>();
scan.AddAllTypesOf<IMessageService>();
});
或者您可以显式注入实例。
this.For<IMessageService>().Use<CompositeMessageService>()
.EnumerableOf<IMessageService>().Contains(x =>
{
x.Type<EmailService>();
x.Type<SmsService>();
});
这意味着可以更改您的配置以更改首先调用哪个服务的顺序。根据您当前的设计,这些详细信息被硬编码到接受这两个参数的服务中。
此外,您还可以在不更改设计的情况下添加额外的消息服务或删除现有的消息服务。