特にMVCアプリケーションでNinjectを使用しました。Ninjectを使用してこれを実現する方法は、依存関係の構成またはバインディングにあります。これを行うときは、オブジェクトの存続期間をどのように管理するかを指定します。Webアプリのほとんどの場合、質問で示したように、オブジェクトはリクエストごとになります。
あなたの質問で私が気づいたことの1つは、DomainContextがIDomainServiceオブジェクトによって作成されており、他のオブジェクトによって使用されていることです。ドメインサービスオブジェクトがDomainContextの一種のファクトリである場合、それほど問題はありません。これは、具体的なオブジェクトを提供し、依存関係を注入するようにNinjectを構成する方法の演習になります。
アプリケーションをどのように構成するかについての一般的なガイダンスは次のとおりです。インターフェイスとクラスについて完全に理解していないことに注意してください。
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Ninjectを機能させる最も簡単な方法は、NinjectHttpApplicationクラスからアプリケーションクラスを派生させることです。RegisterRoutesをオーバーライドメソッドに変更する必要があります。また、 CreateKernelと呼ばれるメソッドを実装する必要があります。CreateKernelメソッドは、それ自体がIoCコンテナであるNinjectカーネルを返す役割を果たします。
CreateKernelメソッドでは、Ninjectが提供するAutoControllerModuleがアセンブリをスキャンしてMVCコントローラークラスを探し、それらをコンテナーに登録します。これが意味するのは、これらのコントローラーへの依存関係は、Ninjectがアプリケーションのコントローラープロバイダーになったため、Ninjectによって注入できるようになったということです。ServiceModuleクラスは、すべてのサービスをNinjectに登録するために作成する必要があるクラスです。私はそれがこのように見えるだろうと推測しています:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninjectは、構成のための非常に表現力豊かな流暢なインターフェイスを備えています。上記のように、各ステートメントは基本的に具象クラスをそれが実装するインターフェースに関連付けます。ステートメントの「Using」句は、オブジェクトがリクエストの存続期間中のみ存続することをNinjectカーネルに示します。したがって、たとえば、これは、同じ要求中にNinjectカーネルからIDomainServiceオブジェクトが要求されるたびに、同じオブジェクトが返されることを意味します。
あなたのコンテキストオブジェクトに関しては、私はあなたのドメインサービスがこれらのコンテキストを作成し、ある種のファクトリとして機能することを突き止めています。その点で、IDomainServiceからCurrentDomainContextというプロパティの値を取得することによって生成されるように、上記のインスタンスDomainContextクラスをバインドしました。それが上記のラムダが達成することです。Ninjectの「ToMethod」バインディングの良いところは、カーネルを使用してオブジェクトを解決できるNinjectアクティベーションコンテキストオブジェクトにアクセスできることです。これは、現在のドメインコンテキストを取得するために行うことです。
次のステップは、オブジェクトが依存関係を適切に受け入れることを確認することです。たとえば、ITrainingServiceはTrainingControllerクラスでのみ使用されると言います。したがって、その場合、TrainingControllerにITrainingServiceパラメーターを受け入れるコンストラクターがあることを確認します。そのコンストラクターでは、 ITrainingServiceへの参照をメンバー変数に保存できます。のように:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
NinjectはすでにすべてのコントローラーをNinjectカーネルに登録しているため、このコントローラーが作成されてそのアクションが呼び出されると、trainingServiceメンバー変数を介してITrainingServiceへの参照が作成されます。
これがお役に立てば幸いです。IoCコンテナの使用は、非常に混乱する場合があります。注:Ninjectのドキュメントを確認することを強くお勧めします。これは、DI/IoCの概念だけでなくNinjectの非常によく書かれた入門書です。上記のAutoWiringModuleについての説明も省略しました。ただし、Nate Kohari(Ninjectの作成者)は、この機能について彼のブログに優れた記事を書いています。
幸運を!