2017-07-11 11 views
1

実行時データに基づいて特定のサービスクラスを使用する必要があるワークフローがあります。SimpleInjectorを使用した戦略パターン

たとえば、私はの依存性を持つSendEmailCommandを持っており、2つの実装はMandrillEmailServiceSmtpEmailServiceです。

SendEmailCommandは、実行時に使用するIEmailServiceの実装を決定します。

各電子メールサービスの実装には、それぞれ独自の依存関係があります。これらは、SimpleInjectorによって配線されています。

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? 
    } 
} 

サービスは、私は推測している戦略に置換することができます。

答えて

1

私にとって最も明白な解決策は、メールサービスの実装にディスパッチすることを可能にする新しい抽象化を定義し、それにランタイムデータを供給することです。これは、次のようになります。

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; 
関連する問題