C# structuremap-同一接口的两个实现
我有一个服务类,包含以下内容:C# structuremap-同一接口的两个实现,c#,dependency-injection,inversion-of-control,structuremap,C#,Dependency Injection,Inversion Of Control,Structuremap,我有一个服务类,包含以下内容: public class (IMessageService emailService, IMessageService smsService) { ... } 以及两种IMessageService(电子邮件和短信)的实现。如何配置容器以正确解析此构造函数?这是命名实例出现的地方,还是另一种情况下的情况?结果表明,命名实例是一种可能的解决方案: _.For<IMessageService >().Use<EmailService>().
public class (IMessageService emailService, IMessageService smsService)
{ ... }
以及两种
IMessageService
(电子邮件和短信)的实现。如何配置容器以正确解析此构造函数?这是命名实例出现的地方,还是另一种情况下的情况?结果表明,命名实例是一种可能的解决方案:
_.For<IMessageService >().Use<EmailService>().Named("emailService");
_.For<IMessageService >().Use<EmailService>().Named("smsService");
\uuu.For().Use().Named(“emailService”);
_.For().Use().Named(“smsService”);
您可以使用命名实例或智能实例来解决此问题
// 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);
然后,您的原始服务只需要接受IMessageService
的一个实例。它不需要知道所处理的IMessageService
类型的详细信息
public SomeService(IMessageService messageService)
在StructureMap中,您可以轻松注册IMessageService的所有实例,它将自动将它们注入IMessageService的构造函数参数数组中
this.Scan(scan =>
{
scan.TheCallingAssembly();
scan.AssemblyContainingType<IMessageService>();
scan.AddAllTypesOf<IMessageService>();
});
this.Scan(扫描=>
{
扫描。卡入总成();
scan.AssemblyContainingType();
scan.AddAllTypesOf();
});
或者可以显式地注入实例
this.For<IMessageService>().Use<CompositeMessageService>()
.EnumerableOf<IMessageService>().Contains(x =>
{
x.Type<EmailService>();
x.Type<SmsService>();
});
this.For().Use()
.EnumerableOf().Contains(x=>
{
x、 类型();
x、 类型();
});
这意味着您可以更改配置,以更改首先调用哪个服务的顺序。在您当前的设计中,这些细节将硬编码到接受这两个参数的服务中
此外,您还可以在不更改设计的情况下添加其他消息服务或删除现有消息服务。//首先只需在IOC中的以下行中书写即可
//First just write below lines in IOC
this.For<IMessageService>().Use<EmailService>();
this.For<IMessageService >().Use<EmailService>();
//Then We can directly use it in our constructor injection of our class
//Where we need it
IEnumerable<IMessageService> messageServices;
public ClassNeedsInjection(IEnumerable<IMessageService> messageServices)
{
this.messageServices=messageServices;
foreach (var messageService in this.messageServices)
{
//use both the objects as you wish
}
}
this.For().Use();
this.For().Use();
//然后我们可以在类的构造函数注入中直接使用它
//我们需要它的地方
IEnumerable消息服务;
公共类需求注入(IEnumerable messageServices)
{
this.messageServices=messageServices;
foreach(此.messageServices中的var messageService)
{
//根据需要使用这两个对象
}
}
不需要太复杂。只需注册一个接口的所有实现
this.For<IMessageService >().Use<EmailService>();
this.For<IMessageService >().Use<SmsService>();
this.For().Use();
this.For().Use();
然后structuremap将自动将IMessageService接口的所有实现注入任何具有接口IEnumerable/list/array的构造函数中。如下图所示:
private IEnumerator<IMessageService> _current;
public SomeClass(IEnumerable<IMessageService> features) {
_current = features.GetEnumerator();
}
private IEnumerator\u当前;
公共类(IEnumerable特性){
_当前=功能。GetEnumerator();
}
希望这有助于一个非常棒的答案,一个真正的大开眼界者。你有什么建议可以帮助你发现复合模式可以这样使用的实例吗?简单回答-一个具有多个相同类型依赖项的服务是一种代码气味,在这里可以使用复合模式或装饰模式。至于进入正确的心态,我个人是通过阅读和一些尝试和错误达到目的的。有许多问题是设计模式可以解决的,而单靠DI是无法解决的,这本书非常适合教授何时以及如何应用这些模式。。。其中包括复合材料。。。这需要一个数组。。。等等?你的代码格式出了问题。请查阅您的帖子。谢谢Bhargav Rao
private IEnumerator<IMessageService> _current;
public SomeClass(IEnumerable<IMessageService> features) {
_current = features.GetEnumerator();
}