我会建议您结合您的IEmail
和ISms
接口为IMessageService
(前提是不违反Liskov Substitution Principal),并使用strategy pattern,使您的通知服务,可以选择的类型(或种)使用的是IMessageService
。
重构到IMessageService
public interface IMessageService
{
void Send(string subject, string body);
bool AppliesTo(IEnumerable<string> providers);
}
public class EmailMessageService : IMessageService
{
public EmailMessageService(/* inject dependencies (and configuration) here */)
{
// Set dependencies to private (class level) variables
}
public void Send(string subject, string body)
{
// Implementation - use dependencies as appropriate
}
public bool AppliesTo(IEnumerable<string> providers)
{
return providers.Contains("email");
}
}
public class SmsMessageService : IMessageService
{
public SmsMessageService(/* inject dependencies (and configuration) here */)
{
// Set dependencies to private (class level) variables
}
public void Send(string subject, string body)
{
// Implementation - use dependencies as appropriate
}
public bool AppliesTo(IEnumerable<string> providers)
{
return providers.Contains("sms");
}
}
实施战略格局
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);
}
}
}
}
使用
在您的DI容器,注册匹配IMessageService
被解析为一个数组,所有类型。例如,在结构图中:
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>();
}));
无论哪种方式,与容器注册类型是所有你需要满足IMessageService[]
依赖。
然后,只需要将IMessageStrategy
注入需要消息传递并传递魔术字符串以选择使用哪种类型的消息服务的类。
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");
}
}
请注意,如果你采用这种方法,您EmailStrategy
类并不需要改变,如果您稍后决定添加或删除IMessageService
- 你只需要改变DI配置。