0

今日、私はこのクラスを持っている:依存性注入 - ロジックをオーバーロードされたコンストラクタに配置しますか?

public class SmtpEmailProvider : IMessageProvider 
{ 
    private readonly SmtpClientWrapper _smtpClientWrapper; 

    public SmtpEmailProvider(SmtpClientWrapper smtpClientWrapper) 
    { 
     _smtpClientWrapper = smtpClientWrapper; 
    } 

はSmtpClientを模擬できるようにするために、私はこのようにそれを包みました:

public class SmtpClientWrapper 
{ 
    private readonly SmtpClient _smtpClient; 

    public SmtpClientWrapper(SmtpClient smtpClient) 
    { 
     _smtpClient = smtpClient; 
    } 

    public virtual void Send(MailMessage msg) 
    { 
     if (_smtpClient == null) throw new InvalidOperationException("SmtpClient must be passed to the constructor before calling Send."); 

     _smtpClient.Send(msg); 
    } 
} 

今私はSmtpEmailProviderを開始するには、これを行うことができますクラス、およびそこSmtpClientロジックを配置します。

public IMessageProvider LocateProviderByName(string providerName) 
{ 
    var client = new SmtpClient 
        { 
         Host = "127.0.0.1", 
         Port = 25 
        }; 
    client.Credentials = new NetworkCredential("...", "..."); 
    return new SmtpEmailProvider(new SmtpClientWrapper(client)); 
} 

をしかし、私はそれを交換したい:

public IMessageProvider LocateProviderByName(string providerName) 
{ 
    return IoC.Resolve<IMessageProvider>(providerName); 
} 

次に、ロジックをパラメータなしでコンストラクタに配置する必要があります。しかし、私はその時、コンストラクターでずっとやっているような気持ちになります。

他の方法はありますか?

答えて

2

私はちょうどあなたが達成しようとしているものについて少し混乱しています。あなたがSmtp電子メールを提供する必要があり、IoCを使用していると仮定するなら、IoCフレームワークを使ってオブジェクトグラフ全体を作成して配線する必要があります。つまり、SmtpClientを作成するようにIoCフレームワークを設定し、SmtpClientWrapperを作成して、SmtpEmailProviderを作成します。 SmtpEmailProviderコンストラクタに依存関係作成ロジックを配置する必要はありません。ここで

は、あなたが提供するコード与えられ、城ウィンザーでの例です:

public IMessageProvider LocateProviderByName(string providerName) 
{ 
    return IoC.Resolve<IMessageProvider>(providerName); 
} 

var messageProvider = LocateProviderByName("smtpProvider"); 

キーポイント:

<configuration> 
    <component id="smtpClient" type="System.Net.Mail.SmtpClient, System"> 
    <parameters> 
     <Host>127.0.0.1</Host> 
     <Port>25</Port> 
    </parameters> 
    </component> 
    <component id="smtpClientWrapper" type="Naespace.SmtpClientWrapper, Assembly"> 
    <parameters> 
     <smtpClient>${smtpClient}</smtpClient> 
    </parameters> 
    </component> 
    <component id="smtpProvider" service="Namespace.IMessageProvider, Assembly" type="Namespace.SmtpEmailProvider, Assembly"> 
    <parameters> 
     <smtpClientWrapper>${smtpClientWrapper}</smtpClientWrapper> 
    </parameters> 
    </component> 
</configuration> 

を上記ウィンザーの構成では、単にそのようなあなたのIMessageProviderを作成することができますここでは、IoCコンテナを使用することです:あなたのために完全なオブジェクトグラフを作成する必要がある依存関係の作成と管理システム。これは、コンストラクタ内の依存性管理ロジックが多すぎるという問題を軽減します。

+0

+ 1私に物事を行う方法の新しいアイデアを与えるため。 しかし、論理にはIoCで指定できるものだけではないと言えます。同様に、私はいくつかのパラメータに応じて、他の設定リポジトリからホスト/ポートをフェッチできる必要があります。 ロジックを配置する正しい場所はどこですか? – Allrameest

+1

この種の機能が必要な場合は、必要なもののインスタンスではなく、注入可能な別のプロバイダまたはファクトリを作成します。たとえば、SmtpClientにホスト、ポート、および資格情報を動的に割り当てる必要があるようです。 SmtpClientFactoryを作成してSmtpClientWrapperに注入します。 SmtpClientWrapperは内部的にSmtpClientの内部インスタンスを作成し、必要に応じてキャッシュすることができます.Mockabilityを維持するために重要なのは、SmtpClientFactoryに仮想メソッドがあることを確認することです。 – jrista

+0

私が気にしていたことが工場でした。私はそれに行くよ! :) – Allrameest