2013-05-06 7 views
13

現時点では、私は依存性注入容器を少し実験していますが、今回はUnityを使っています。依存性注入と他のコンストラクタパラメータ - 悪い習慣?

public interface IPodcastCommService 
{ 
    void Download(); 

    void Upload(); 
} 

と次の実装:

は、次のインターフェイスを考えるため、コンストラクタの

public class PodcastService 
{ 
    private IPodcastCommService commservice; 
    private String url; 

    public PodcastService(String url, IPodcastCommService commservice) 
    { 
     this.commservice = commservice; 
     this.url = url; 
    } 
} 

を、私はそれにパラメータを渡すための解決策を探していましたし、それを見つけた:

var p = container.Resolve<IPodcastCommService>(new ParameterOverride("url", myUrl)); 

これまでのところ非常に優れていましたが、同時にこれがどれほど悪く、どのように悪いクラスのデザインとはい、それは少し醜いように見えます。しかし、どのようにクラスにパラメータをエレガントな方法で渡すことができますか?

私が最初に思ったのは、プロパティとして行うことでしたが、その後、既に与えられているURLが必要なたびにチェックする必要がありました。

アップデート:

しかし、あなたは解決操作用のカスタムコンストラクタのパラメータを渡す必要があり場合もある。 一例として、私はこれは悪いデザインであることを読んで、これです。これは悪いアーキテクチャの叫び声だと主張する人もいるかもしれませんが、DIコンテナをレガシーシステムに持ち込んでこの種の行動が必要な状況があります。

出典:http://mikaelkoskinen.net/unity-passing-constructor-parameters-to-resolve/

+1

あなたはどこが赤で、これが悪いデザインであるか教えていただけますか?私は実際にこのデザインがあなたが得られる最高のものだと思っているからです。 – Egi

+0

@Egi:質問をソースで更新しました。 – Kai

+0

[ServiceLocator](https://commonservicelocator.codeplex.com/)を使用すると、コンストラクタに注入されたプロパティをリストしなくてもDIを実行できます。 – orad

答えて

3

IPodcastCommServiceの代わりにIPodcastCommServiceのPodcastServiceが必要で、URLが文字列で注入されている理由がわかりません。なぜあなたのデザインが悪いのか分かりません。注入URLは良いIMHOです。

あなたが良い方法を考えるなら、私はそれがネイティブデータタイプの代わりにコンテキスト/設定を注入することによって置き換えられると思います。

public class PodcastService 
{ 
    private IPodcastCommService commservice; 
    private IConnectionContext connection; 

    public PodcastService(IConnectionContext connection, IPodcastCommService commservice) 
    { 
     this.commservice = commservice; 
     this.connection= connection; 
    } 
} 

public interface IConnectionContext{ 
    string PodcastServiceUrl{get;} 
} 

しかし、再び通常のアプローチからの(セッション/定数/静的フィールドを処理することができますを除いて)、私はそれからどんな恩恵を見つけることができません。

UPDATE:

私は悪いデザインhereについて似質問を発見しました。つまり、ネイティブ型のパラメータ(文字列など)やカスタムコンストラクタのパラメータが悪いというわけではありません。パラメータを実際に担当するクラスにパラメータを配置する必要があるだけです。抽象的なファクトリパターン内でif-else条件を処理する場合、カスタムコンストラクタパラメータが必要になります。

-3

ゆうが使用しているフレームワークに依存します。たとえば、DependecyResolverのようなIoCコンテナのasp.net mvc providers統合ポイントです。オブジェクトを構築し、依存関係を注入するためのすべてのロジックを配置する必要があります。 aps.netを使用している場合、preinit eevntが依存関係を注入する何らかの基本ページがあるかもしれません。 asp.netでコンストラクタインジェクションを使用することはできません。プロパティインジェクションのみです。 winformsを使用すると、ある種のフォームファクトリを使用してフォームオブジェクトを構築できます。

1

あなたのシナリオでは、コンストラクタ経由のDIは完全にうまくいくと思います。プロパティを経由するより良いアプローチと考えられる理由は、読みやすさを向上させるために、つまり20個のプロパティを注入する必要がある場合に、コンストラクタがどのように見えるかを想像するからです。

あなたはいくつかのプロパティを注入するつもりなら、あなたのやっていることを害することは絶対にありません。私はあなたの依存関係が這い上がるのを見つけたら、プロパティ型のアプローチに移行することを考えています。

+2

注射が2回以上ある場合、 'Builder'パターンを使用して読みやすさを簡素化できます。私は、オブジェクト*が使用される前にプロパティを設定する必要がある場合、プロパティを使用するよりもはるかに優れていると思います。 –

+2

コンストラクタに20個の引数がある場合は、クラスがSRPを痛感し、読みやすくするためにプロパティ注入を悪用する代わりに、より小さなクラスにリファクタリングする必要があります。実行時に変更できる動的な振る舞いが必要な場合は、私の意見ではプロパティインジェクションをお勧めします。 – Egi

1

たぶん

container.RegisterType<PodcastService>(new InjectionConstructor("myUrlParameter")); 

が良いだろう、それはないでしょうか?

しかし、複数のpodcastサービスが必要で、別のURLが必要な場合は、parameteroverrideはOKです。