2016-09-28 2 views
0

IOC/DIコンテナを使用しようとしていますが、子ウィンドウを作成するときには何がベストプラクティスですか?IOC/DIコンテナと子ウィンドウ作成のジレンマ

私が午前ジレンマがある:

public class ParentWindow : Form 
{ 
    public void OpenChildWindow() 
    { 
     var child = IocContainer.Instance.Resolve<ChildWindow>(); // big issue !!! an-ti server locator pattern 
     child.Show(); 
    } 
} 

それとも

public class ParentWindow : Form 
    { 

      private Container _container 

      public ParentWindow(Container container) // no, no, you have dependence on container 
      { 
      } 

     public void OpenChildWindow() 
     { 
      var child = _container.Resolve<ChildWindow>(); 
      child.Show(); 
     } 
    } 

私のソリューション

public class ParentWindow : Form 
{ 
    private IFormFactory _factory 

    public ParentWindow(IFormFactory factory) // inject from IOC container 
    { 
    } 

    public void OpenChildWindow() 
    { 
     var child = _factory.CreateChildWindow(); 
     child.Show(); 
    } 
} 

しかし、私の解決策と 、一種の私自身のIOCのコンテナになる私の工場、すべての私の親の窓は工場で渡さなければなりません、これは私の工場を新しい "サーバロケータ"にするのではないのですか?

他にもこれは良い解決策がありますか?

+0

関連:https://stackoverflow.com/questions/38417654/winforms-how-to-register-forms-with-ioc-container/38421425#38421425 – Steven

+0

@Stevenは私の問題を解決しません – LeY

答えて

0

DIを使用するということは、コンテナをサービスロケータとして、好ましくは1回だけ実行するコードの1行で消費することを意味します。これはコンテナが構成され、オブジェクトグラフのルートが作成される「コンポジションルート」と呼ばれます。

あなたの例の最上位のコードはこの原則に違反していません。

追記:

私がいつもやっていることは、私はDIがよりeasily-はそれを考慮するフレームワークに切り替えることができるように自分のクラスにコンテナフレームワークのコードをラップです。

+0

DIを使用していません容器を直接消費することを暗示している。スタック全体に明示的に依存関係を持たせることは、コードの匂いとみなすことさえできます。コンポジション・ルートとローカル・ファクトリーの両方を組み合わせることで、コンテナのスタックとコンシューマの依存関係のないすべてのローカル・ファクトリを使用することができます。 –

+0

私は完全に同意します、そしてこれはまさに私が言ったことです - あなたが慎重に - 私が言及しなかった地元の工場の部分を読めば - (答えが分かりやすいように編集しました)。 @WiktorZychla –

+0

CRはストーリーの半分に過ぎないことに注意してください。そこにコンテナを設定することはできますが、コンテナをスタックに渡す必要があります。地元の工場のアイデアは残りの半分です。地元の工場を使用すると、コンテナを参照する必要がなくなります。 –

1

あなたが提案する解決策は、正しい方向に大きなステップです。工場は実際にはロケータのような匂いをしません。むしろ、それが所属するドメインの一部であるローカルファクトリです。

さらに、工場のファミリ(インターフェイス)のアイデアを忘れて、内部的にコンテナを使用する(または使用しない)プラグイン可能な実装を持つコンクリート工場を持っていますが、クライアント。このようにして、コンストラクタのコンストラクタをフォームに挿入して、ファクトリの具体的な型を使用するだけで済みます。工場自体は、構成ルートに構成されています。私のブログのエントリ

http://www.wiktorzychla.com/2016/01/di-factories-and-composition-root.html

0

最初の例では

詳細およびコード例は:あなたも依存することができますないユニットテストを持っているので、私は好きではありません。それはChildWindowのインスタンスを解決し、あなたはそれを制御できません。

第2の例:クラスコンテナを使用していないため、私は好きではありません。

3番目の例:以前よりもうまく動作し、時にはその方法で工場を使用します。それはそれが完全にユニットテストすることができます。

通常、私はDI容器を工場として使用するほうが良いと考えています。オブジェクトの寿命...

私は決してクラスChildWindowを使用しませんでしたが、コンストラクタインターフェイスで定義できない場合は、ChildWindowWrapper:IChildWindowWrapperを実装し、そのラッパーを使用します。単体テストを行い、DIコンテナから使用することができます。

+0

あなたは "DI容器を工場として使う"と "ChildWindowWrapper"の例を提供することができます – LeY

+0

@LeY申し訳ありませんが、音が曖昧です。ファクトリパターン(メソッド)を使用する代わりに、オブジェクトの新しいインスタンスを作成するためにDIコンテナを使用することにします。たとえば、classがInterfaceクラスまたはAbstractクラスを実装していない場合、私はラッパークラスを使用します。 Wrapperは、必要な特定の機能をカプセル化するクラスです。クラスのコードを直接使用する代わりに、Wrapperを直接使用する必要があります。ラッパーはインターフェイスを実装する必要があり、DIコンテナに登録することができます。 – kat1330

関連する問題