C# 依赖项注入类型选择
最近我遇到了一个问题,我必须根据参数选择一个类型。例如:用于发送通知的类,该类应根据输入参数选择正确的频道(电子邮件、sms等) 我看起来像这样:C# 依赖项注入类型选择,c#,dependency-injection,architecture,C#,Dependency Injection,Architecture,最近我遇到了一个问题,我必须根据参数选择一个类型。例如:用于发送通知的类,该类应根据输入参数选择正确的频道(电子邮件、sms等) 我看起来像这样: public class NotificationManager { IEmail _email; ISms _sms; public NotificationManager (IEmail email, ISMS sms) { _email = email; _sms = sms
public class NotificationManager
{
IEmail _email;
ISms _sms;
public NotificationManager (IEmail email, ISMS sms)
{
_email = email;
_sms = sms;
}
public void Send(string type)
{
switch(type)
{
case "email":
_email.send;
break;
case "sms":
_sms.send;
break;
}
}
}
这里的问题是,当我使用这种构造时,使用所有不同的发送通知的方法,构造函数会快速增长到非常大的规模
我真的不喜欢这样,这使得单元测试这个选择单元变得难以管理
我不能简单地说newemail()代码>因为通知类型的电子邮件将依赖于IEmailManager,这只会解决问题
是否有某种模式可以做到同样的效果,但会以更好、更干净的方式?我建议您将IEmail
和ISms
接口合并到IMessageService
(前提是不违反)中,并使用a使您的通知服务能够选择一种或多种类型所使用的IMessageService
的
重构到IMessageService
或者,您也可以使用扫描自动拾取在事件发生后添加的新类型
var container = new Container(x => x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.AddAllTypesOf<IMessageService>();
}));
请注意,如果采用这种方法,如果您以后决定添加或删除IMessageService
,则您的EmailStrategy
类将不需要更改-您只需要更改DI配置
public interface IMessageStrategy
{
void Send(string message, string body, string provider);
void Send(string message, string body, IEnumerable<string> providers);
}
public class MessageStrategy : IMessageStrategy
{
private readonly IMessageService[] messageServices;
public MessageStrategy(IMessageService[] messageServices)
{
if (messageServices == null)
throw new ArgumentNullException("messageServices");
this.messageServices = messageServices;
}
public void Send(string message, string body, string provider)
{
string[] providers = provider.Split(';').Select(p => p.ToLower().Trim()).ToArray();
this.Send(message, body, providers);
}
public void Send(string message, string body, IEnumerable<string> providers)
{
foreach (IMessageService messageService in messageServices)
{
if (messageService.AppliesTo(providers))
{
messageService.Send(message, body);
}
}
}
}
container.For<IMessageService>().Use<EmailMessageService>();
container.For<IMessageService>().Use<SmsService>();
var container = new Container(x => x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.AddAllTypesOf<IMessageService>();
}));
public class SomeService : ISomeService
{
private readonly IMessageStrategy messageStrategy;
public SomeService(IMessageStrategy messageStrategy)
{
if (messageStrategy == null)
throw new ArgumentNullException("messageStrategy");
this.messageStrategy = messageStrategy;
}
public void DoSomething()
{
// Send a message via email
this.messageStrategy.Send("This is a test", "Hello", "email");
// Send a message via SMS
this.messageStrategy.Send("This is a test", "Hello", "sms");
// Send a message via email and SMS
this.messageStrategy.Send("This is a test", "Hello", "email;sms");
}
}