web-dev-qa-db-ja.com

Ninjectの使用方法

今日はNinjectを使おうとしていますが、いくつか質問があります。まず、インジェクションを使用するすべてのコンストラクターでInject属性を使用する必要がありますか。これは本当に下手なデザインのようですか?カーネルを作成して、注入されたクラスで渡すすべての場所でそれを使用する必要がありますか?

18
Sachin Kainth

まず、インジェクションを使用するすべてのコンストラクターでInject属性を使用する必要がありますか。これは本当に下手なデザインのようですか?

いいえ、実際にこれを行う必要はまったくありません。 ASP.NET MVCを使用しているため、Ninject.MVC3Nugetパッケージをインストールするだけです。これにより、App_StartフォルダーのNinjectMVC3クラスを開始できます。 RegisterServicesメソッドを使用して、インターフェイス/クラスをNinjectに登録できます。これらのインターフェースに依存するすべてのコントローラーは、Ninjectによって自動的に解決されます。Inject属性は必要ありません。

カーネルを作成して、注入されたクラスで渡すすべての場所でそれを使用する必要がありますか?

いいえ-あなたが説明していることは、依存性注入ではなく、 Service Locator pattern のように聞こえます-カーネルを使用して特定のクラス内で依存関係を解決するのではなく、理想的にはコンストラクターで依存関係を渡します。解決が行われる中央のコンポジションルートは1つだけである必要があります。これは、上記のRegisterServicesメソッドまたはそこでインスタンス化された別のNinjectモジュールのコンポジションルート内にあります。後者のアプローチでは、もう少し柔軟性があります。依存関係を解決する方法を変更する際のモジュール性(しゃれは意図されていません)。

これが良い NinjectとMVC3を使用した依存性注入に関する初心者向けチュートリアル です。

22
BrokenGlass

Ninjectを使い始めるための最良の方法は、小さなことから始めることです。 newを探します。

アプリケーションの途中で、別のクラス内にクラスを作成しています。つまり、dependencyを作成しているということです。依存性注入とは、埋め込みの代わりに、通常はコンストラクターを介して、渡すこれらの依存性です。

このようなクラスがあり、Wordで特定の種類のメモを自動的に作成するために使用されているとします。 (これは私が最近仕事で行ったプロジェクトに似ています。)

class NoteCreator
{
    public NoteHost Create()
    {
        var docCreator = new WordDocumentCreator();
        docCreator.CreateNewDocument();
        [etc.]

WordDocumentCreatorは、Microsoft Wordで新しいドキュメントを作成する(Wordのインスタンスを作成するなど)詳細を処理するクラスです。私のクラス、NoteCreatorWordDocumentCreatorに依存してその作業を実行します。

問題は、いつか優れたワードプロセッサに移行することにした場合、WordDocumentCreatorがインスタンス化されるすべての場所を見つけて、代わりにWordPerfectDocumentCreatorをインスタンス化するように変更する必要があることです。

ここで、クラスを次のように変更するとします。

class NoteCreator
{
    WordDocumentCreator docCreator;

    public NoteCreator(WordDocumentCreator docCreator)  // constructor injection
    {
        this.docCreator = docCreator;
    }

    public NoteHost Create()
    {
        docCreator.CreateNewDocument();
        [etc.]

私のコードはそれほど変わっていません。 Createメソッド内で行ったのは、newの行を削除することだけです。しかし今、私は自分の依存関係を注入しています。もう1つ小さな変更を加えましょう。

class NoteCreator
{
    IDocumentCreator docCreator;

    public NoteCreator(IDocumentCreator docCreator)  // change to interface
    {
        this.docCreator = docCreator;
    }

    public NoteHost Create()
    {
        docCreator.CreateNewDocument();
        [etc.]

concreteWordDocumentCreatorを渡す代わりに、IDocumentCreatorメソッドを使用してCreateNewDocumentinterfaceを抽出しました。これで、そのインターフェイスを実装するanyクラスを渡すことができ、NoteCreatorが行う必要があるのはそれが知っているメソッドを呼び出すことだけです。

ここで注意が必要な部分存在しないパラメーターのないコンストラクターを使用してNoteCreatorを作成していたため、アプリでコンパイルエラーが発生するはずです。ここで、that依存関係も引き出す​​必要があります。つまり、上記と同じプロセスを実行しますが、新しいNoteCreatorを作成するクラスに適用しています。依存関係の抽出を開始すると、アプリケーションのルートに「バブルアップ」する傾向があることがわかります。これは、onlyの場所であり、 DIコンテナ(例:Ninject)。

私がする必要がある他のことはconfigureNinjectです。重要な部分は、次のようなクラスです。

class MyAppModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDocumentCreator>()
            .To<WordDocumentCreator>();

これは、Ninjectに、どこかでIDocumentCreatorを必要とするクラスを作成しようとすると、WordDocumentCreatorを作成してそれを使用する必要があることを伝えます。 Ninjectが実行するプロセスは、次のようになります。

  • アプリケーションのMainWindowを作成します。そのコンストラクターにはNoteCreatorが必要です。
  • では、NoteCreatorを作成します。ただし、itsコンストラクターにはIDocumentCreatorが必要です。
  • 私の構成では、IDocumentCreatorには、WordDocumentCreatorを使用する必要があると書かれています。したがって、WordDocumentCreatorを作成します。
  • これで、WordDocumentCreatorをNoteCreatorに渡すことができます。
  • そして今、私はそのNoteCreatorMainWindowに渡すことができます。

このシステムの美しさは3つあります。

まず、何かを構成しなかった場合、アプリケーションが実行されるとすぐにオブジェクトが作成されるため、すぐにわかります。 Ninjectは、(たとえば)IDocumentCreatorを解決できないことを示す有用なエラーメッセージを表示します。

第二に、管理者が後で優れたワードプロセッサのユーザーを義務付けた場合、あなたがしなければならないのは

  • WordPerfectDocumentCreatorを実装するIDocumentCreatorを記述します。
  • 上記のMyAppModuleを変更し、代わりにIDocumentCreatorWordPerfectDocumentCreatorにバインドします。

第三に、NoteCreatorをテストしたい場合は、realWordDocumentCreator(または使用しているもの)を渡す必要はありません。 )。 偽のものを渡すことができます。そうすれば、仮定私のIDocumentCreatorが正しく機能し、NoteCreator自体の可動部分のみをテストするテストを作成できます。私の偽のIDocumentCreatorは正しい応答を返すだけで、私のテストではNoteCreatorが正しいことをすることを確認します。

この方法でアプリケーションを構造化する方法の詳細については、Mark Seemannの最近の本 。NETでの依存関係の注入 を参照してください。残念ながら、Ninjectについては説明していませんが、他の多くのDIフレームワークについては説明しており、上記の方法でアプリケーションを構造化する方法について説明しています。

マイケル・フェザーズによる レガシーコードで効果的に作業する もご覧ください。彼は、上記のテストの側面について話します。動作を分離してテストするために、インターフェイスを分割して偽物を渡す方法です。

58
Ryan Lundy

あなたが尋ねている種類の質問を考えると、私が非常に適切だと思うイントロを含むドキュメントがあることを忘れないでください Ninject Wikiで 。 Ninjectを端から端まで読まずに使用しようとすると、煩わしいだけです。

目次 をブックマークバーに少し貼り付けます。

また、DIベースのアーキテクチャのコンパニオンブックとして Mark Seemann 's 。Netの依存関係インジェクション を強くお勧めします(Ninjectを直接カバーしていませんが)。

7
Ruben Bartelink