web-dev-qa-db-ja.com

Ninjectモジュールの意図は何ですか?

私はninjectの完全な初心者です

私は他の誰かのコードを引き離していて、nInjectモジュールのいくつかのインスタンス-Ninject.Modules.Moduleから派生したクラスを見つけ、それらのコードのほとんどを含むロードメソッドを持っています。

これらのクラスは、StandardKernelのインスタンスのLoadModuleメソッドを呼び出し、モジュールクラスのインスタンスを渡すことによって呼び出されます。

多分私はここで明白な何かを見逃しているかもしれませんが、単純な古いクラスを作成してそのメソッドを呼び出すこと、またはおそらく静的メソッドを持つ静的クラスよりもこれの利点は何ですか?

58
Jonathan

Ninjectモジュールは、さまざまなタイプをIoCコンテナーに登録するために使用されるツールです。利点は、これらのモジュールが独自のクラスに保持されることです。これにより、さまざまな層/サービスを独自のモジュールに配置できます。

// some method early in your app's life cycle
public Kernel BuildKernel()
{
    var modules = new INinjectModule[] 
    {
        new LinqToSqlDataContextModule(), // just my L2S binding
        new WebModule(),
        new EventRegistrationModule()
    };
    return new StandardKernel(modules);
}

// in LinqToSqlDataContextModule.cs
public class LinqToSqlDataContextModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository>().To<LinqToSqlRepository>();
    }
}

複数のモジュールを使用すると、IoCコンテナー内でも懸念事項を分離できます。

残りの質問は、Ninjectだけでなく、IoCとDI全体に関するもののようです。はい、静的構成オブジェクトを使用して、IoCコンテナーが行うほぼすべてのことを実行できます。依存関係の階層が複数ある場合、IoCコンテナーは本当に便利になります。

public interface IInterfaceA {}
public interface IInterfaceB {}
public interface IInterfaceC {}

public class ClassA : IInterfaceA {}

public class ClassB : IInterfaceB
{
    public ClassB(IInterfaceA a){}
}

public class ClassC : IInterfaceC
{
    public ClassC(IInterfaceB b){}
}

ClassCを構築することは、この時点で面倒であり、複数の深さのインターフェースがあります。カーネルにIInterfaceCを要求する方がはるかに簡単です。

var newc = ApplicationScope.Kernel.Get<IInterfaceC>();
61
Jarrett Meyer

多分私はここで明白な何かを見逃しているかもしれませんが、単純な古いクラスを作成してそのメソッドを呼び出すこと、またはおそらく静的メソッドを持つ静的クラスよりもこれの利点は何ですか?

はい。モジュールなしで、一連のBind<X>().To<Z>()ステートメントを呼び出してバインディングをセットアップできます。

違いは、これらのステートメントをモジュールに配置すると、次のようになるということです。

  • IKernel.Load(IEnumerable<Assembly>)は、リフレクションを介してそのようなモジュールを動的に検出し、それらをロードできます。
  • バインディングは名前の下で論理的にグループ化されます。この名前を使用して、IKernel.Unload(string)で再度アンロードできます。
9
Wim Coenen

多分私はここで明白な何かを見逃しているかもしれませんが、単純な古いクラスを作成してそのメソッドを呼び出すこと、またはおそらく静的メソッドを持つ静的クラスよりもこれの利点は何ですか?

私たちにとっては、後で非常に簡単にテストを追加できる機能です。いくつかのバインディングをmockobjectsとvoilaでオーバーライドするだけです。「すべて」を配線するDIのないレガシーコードでは、リワークなしでテストケースの挿入を開始することはほぼ不可能です。 DIが配置されていて、DIがすべてを配線した場所で適切に使用されていれば、非常に醜い可能性があるレガシーコードでも簡単に実行できます。

多くのDIフレームワークでは、mockobjectsによる特定のバインディングをオーバーライドするテストモジュールを使用して、テスト用のプロダクションモジュールを使用できます(残りの配線はそのままにします)。これらは単体テストよりもシステムテストの可能性がありますが、クラス間の統合をテストするため、平均的な開発者よりも高いレベルのテストを好む傾向があり、プロジェクトに参加して機能全体を実際に見ることができる優れたドキュメントです(代わりに機能の一部のみ)システム全体をセットアップする必要はありません)。

3
Dean Hiller