今日はNinjectを使おうとしていますが、いくつか質問があります。まず、インジェクションを使用するすべてのコンストラクターでInject属性を使用する必要がありますか。これは本当に下手なデザインのようですか?カーネルを作成して、注入されたクラスで渡すすべての場所でそれを使用する必要がありますか?
まず、インジェクションを使用するすべてのコンストラクターでInject属性を使用する必要がありますか。これは本当に下手なデザインのようですか?
いいえ、実際にこれを行う必要はまったくありません。 ASP.NET MVCを使用しているため、Ninject.MVC3Nugetパッケージをインストールするだけです。これにより、App_StartフォルダーのNinjectMVC3
クラスを開始できます。 RegisterServices
メソッドを使用して、インターフェイス/クラスをNinjectに登録できます。これらのインターフェースに依存するすべてのコントローラーは、Ninjectによって自動的に解決されます。Inject属性は必要ありません。
カーネルを作成して、注入されたクラスで渡すすべての場所でそれを使用する必要がありますか?
いいえ-あなたが説明していることは、依存性注入ではなく、 Service Locator pattern のように聞こえます-カーネルを使用して特定のクラス内で依存関係を解決するのではなく、理想的にはコンストラクターで依存関係を渡します。解決が行われる中央のコンポジションルートは1つだけである必要があります。これは、上記のRegisterServices
メソッドまたはそこでインスタンス化された別のNinjectモジュールのコンポジションルート内にあります。後者のアプローチでは、もう少し柔軟性があります。依存関係を解決する方法を変更する際のモジュール性(しゃれは意図されていません)。
これが良い NinjectとMVC3を使用した依存性注入に関する初心者向けチュートリアル です。
Ninjectを使い始めるための最良の方法は、小さなことから始めることです。 new
を探します。
アプリケーションの途中で、別のクラス内にクラスを作成しています。つまり、dependencyを作成しているということです。依存性注入とは、埋め込みの代わりに、通常はコンストラクターを介して、渡すこれらの依存性です。
このようなクラスがあり、Wordで特定の種類のメモを自動的に作成するために使用されているとします。 (これは私が最近仕事で行ったプロジェクトに似ています。)
class NoteCreator
{
public NoteHost Create()
{
var docCreator = new WordDocumentCreator();
docCreator.CreateNewDocument();
[etc.]
WordDocumentCreator
は、Microsoft Wordで新しいドキュメントを作成する(Wordのインスタンスを作成するなど)詳細を処理するクラスです。私のクラス、NoteCreator
、はWordDocumentCreator
に依存してその作業を実行します。
問題は、いつか優れたワードプロセッサに移行することにした場合、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
メソッドを使用してCreateNewDocument
interfaceを抽出しました。これで、そのインターフェイスを実装する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
が必要です。IDocumentCreator
が必要です。IDocumentCreator
には、WordDocumentCreator
を使用する必要があると書かれています。したがって、WordDocumentCreator
を作成します。WordDocumentCreator
をNoteCreatorに渡すことができます。NoteCreator
をMainWindow
に渡すことができます。このシステムの美しさは3つあります。
まず、何かを構成しなかった場合、アプリケーションが実行されるとすぐにオブジェクトが作成されるため、すぐにわかります。 Ninjectは、(たとえば)IDocumentCreator
を解決できないことを示す有用なエラーメッセージを表示します。
第二に、管理者が後で優れたワードプロセッサのユーザーを義務付けた場合、あなたがしなければならないのは
WordPerfectDocumentCreator
を実装するIDocumentCreator
を記述します。MyAppModule
を変更し、代わりにIDocumentCreator
をWordPerfectDocumentCreator
にバインドします。第三に、NoteCreator
をテストしたい場合は、realWordDocumentCreator
(または使用しているもの)を渡す必要はありません。 )。 偽のものを渡すことができます。そうすれば、仮定私のIDocumentCreator
が正しく機能し、NoteCreator
自体の可動部分のみをテストするテストを作成できます。私の偽のIDocumentCreator
は正しい応答を返すだけで、私のテストではNoteCreator
が正しいことをすることを確認します。
この方法でアプリケーションを構造化する方法の詳細については、Mark Seemannの最近の本 。NETでの依存関係の注入 を参照してください。残念ながら、Ninjectについては説明していませんが、他の多くのDIフレームワークについては説明しており、上記の方法でアプリケーションを構造化する方法について説明しています。
マイケル・フェザーズによる レガシーコードで効果的に作業する もご覧ください。彼は、上記のテストの側面について話します。動作を分離してテストするために、インターフェイスを分割して偽物を渡す方法です。
あなたが尋ねている種類の質問を考えると、私が非常に適切だと思うイントロを含むドキュメントがあることを忘れないでください Ninject Wikiで 。 Ninjectを端から端まで読まずに使用しようとすると、煩わしいだけです。
目次 をブックマークバーに少し貼り付けます。
また、DIベースのアーキテクチャのコンパニオンブックとして Mark Seemann 's 。Netの依存関係インジェクション を強くお勧めします(Ninjectを直接カバーしていませんが)。