简单注入器的策略模式
Strategy Pattern with Simple Injector
我有一个工作流,其中我需要根据一些 运行 时间数据使用特定服务 class。
例如。我有一个 SendEmailCommand
,其依赖性为 IEmailService
,具有 MandrillEmailService
和 SmtpEmailService
.
的 2 个实现
SendEmailCommand
将决定它在 运行 时使用哪个 IEmailService
的实现。
每个电子邮件服务实现都有自己的依赖项,由简单注入器连接。
我不确定 SendEmailCommand
将如何确定要使用的实现 (IEmailService
) 或如何将这些服务与 运行 时间数据连接起来。
一些代码:
SendEmailCommand.cs 处理程序
public void Handle(SendEmail command) {
IEmailService service;
if(/* some condition */) {
service = // What to do here?
} else {
service = // What to do here?
}
}
服务可以用我猜的策略代替。
(对我而言)最明显的解决方案是定义一个新的抽象,允许在向邮件服务实现提供运行时数据的同时分派它。这可能看起来像这样:
interface IMailServiceDispatcher
{
void Send([runtime data], [mail service arguments]);
}
这允许您的命令处理程序成为:
private readonly IEmailServiceDispatcher dispatcher;
public void Handle(SendEmail command) {
var data = /* runtime data */
this.dispatcher.Send(data, /* mail service parameters */);
}
现在您可以为 IMailServiceDispatcher
创建一个可能如下所示的实现:
class EmailServiceDispatcher : IEmailServiceDispatcher
{
IMailService man; IMailService smtp;
public EmailServiceDispatcher(IMailService man, IMailService smtp) { ... }
public void Send(runtimeData, parameters) =>
GetService(runtimedData).Send(parameters);
private IMailService GetService(runtimeData) =>
/* some condition using runtime data */ ? man : smtp;
}
您可以按如下方式连接这一切:
container.Register<IMailServiceDispatcher, MailServiceDispatcher>();
container.RegisterConditional<IMailService, MandrillEmailService>(WithParamName("man"));
container.RegisterConditional<IMailService, SmtpEmailService>(WithParamName("smtp"));
// Helper method
private static Predicate<PredicateContext> WithParamName(string name) =>
c => c.Consumer.Target.Name == name;
我有一个工作流,其中我需要根据一些 运行 时间数据使用特定服务 class。
例如。我有一个 SendEmailCommand
,其依赖性为 IEmailService
,具有 MandrillEmailService
和 SmtpEmailService
.
SendEmailCommand
将决定它在 运行 时使用哪个 IEmailService
的实现。
每个电子邮件服务实现都有自己的依赖项,由简单注入器连接。
我不确定 SendEmailCommand
将如何确定要使用的实现 (IEmailService
) 或如何将这些服务与 运行 时间数据连接起来。
一些代码:
SendEmailCommand.cs 处理程序
public void Handle(SendEmail command) {
IEmailService service;
if(/* some condition */) {
service = // What to do here?
} else {
service = // What to do here?
}
}
服务可以用我猜的策略代替。
(对我而言)最明显的解决方案是定义一个新的抽象,允许在向邮件服务实现提供运行时数据的同时分派它。这可能看起来像这样:
interface IMailServiceDispatcher
{
void Send([runtime data], [mail service arguments]);
}
这允许您的命令处理程序成为:
private readonly IEmailServiceDispatcher dispatcher;
public void Handle(SendEmail command) {
var data = /* runtime data */
this.dispatcher.Send(data, /* mail service parameters */);
}
现在您可以为 IMailServiceDispatcher
创建一个可能如下所示的实现:
class EmailServiceDispatcher : IEmailServiceDispatcher
{
IMailService man; IMailService smtp;
public EmailServiceDispatcher(IMailService man, IMailService smtp) { ... }
public void Send(runtimeData, parameters) =>
GetService(runtimedData).Send(parameters);
private IMailService GetService(runtimeData) =>
/* some condition using runtime data */ ? man : smtp;
}
您可以按如下方式连接这一切:
container.Register<IMailServiceDispatcher, MailServiceDispatcher>();
container.RegisterConditional<IMailService, MandrillEmailService>(WithParamName("man"));
container.RegisterConditional<IMailService, SmtpEmailService>(WithParamName("smtp"));
// Helper method
private static Predicate<PredicateContext> WithParamName(string name) =>
c => c.Consumer.Target.Name == name;