私はしばらく Ninject を使用してきましたが、単純な DI のためだけです。対応したい、もう少し複雑なシナリオがあります。
私は Ninject.Web.MVC プラグインをコントローラー インジェクションと共に使用しています。これは、基本コントローラーで強制され、すべての継承コントローラーに渡されます。これが私の基本的なパターンです:
using System;
using System.Web;
using System.Web.Mvc;
using Business;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
namespace Web {
#region Controller
public class MyController : MyBaseController {
public MyController(IMyService1 myService1, IMyService2 myService2)
: base(myService1, myService2) {
}
public ActionResult MyAction() {
MyServiceProp1.DoSomething();
MyServiceProp2.DoSomethingElse();
return View();
}
}
public class MyBaseController : Controller {
protected IMyService1 MyServiceProp1 { get; set; }
protected IMyService2 MyServiceProp2 { get; set; }
public MyBaseController(IMyService1 myService1, IMyService2 myService2) {
MyServiceProp1 = myService1;
MyServiceProp2 = myService2;
}
}
#endregion
}
namespace Business {
#region Services
public interface IMyService1 {
void DoSomething();
}
public interface IMyService2 {
void DoSomethingElse();
}
public class MyService1 : IMyService1 {
public void DoSomething() {
}
}
public class MyService2 : IMyService2 {
public void DoSomethingElse() {
}
}
#endregion
}
#region Ninject stuff
namespace Web.App_Start {
public static class NinjectWebCommon {
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start() {
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop() {
bootstrapper.ShutDown();
}
/// <summary>
/// Creates a kernel that will manage the application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel() {
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Loads modules and services
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel) {
kernel.Bind<IMyService1>().To<MyService1>();
kernel.Bind<IMyService2>().To<MyService2>();
}
}
}
#endregion
ご覧のとおり、私は複数のサービスを持っています。MyService3 を追加したい場合は、ベース コントローラーを実装しているすべてのコントローラーを変更する必要があります。これは現状では大規模な仕事ではありませんが、プロジェクトが大きくなったときになります...
私がやりたいことは、ある種のサービス コンテナーを実装することです。これをベース コントローラーに挿入するため、すべての実装コントローラー (および後続のクラス) を挿入します。
namespace Web {
#region Controller
public class MyController : MyBaseController {
public MyController(IMyServiceContainer container)
: base(container) {
}
public ActionResult MyAction() {
MyServiceProp1.DoSomething();
MyServiceProp2.DoSomethingElse();
return View();
}
}
public interface IMyServiceContainer {
IMyService1 MyServiceProp1 { get; set; }
IMyService2 MyServiceProp2 { get; set; }
}
public class MyBaseController : Controller, IMyServiceContainer {
public MyBaseController(IMyServiceContainer container) {
MyServiceProp1 = container.MyServiceProp1;
MyServiceProp2 = container.MyServiceProp2;
}
#region Implementation of IMyServiceContainer
public IMyService1 MyServiceProp1 { get; set; }
public IMyService2 MyServiceProp2 { get; set; }
#endregion
}
#endregion
}
このようにすると、グローバルな依存関係を追加する必要がある場合に、コントローラーを変更する必要がなく、基本コントローラーだけを変更するだけで済みます。これにより、保守がはるかに簡単になります。
これを Ninject (または Unity で、すぐに変更するので) で実現する方法はありますか?また、パターン/メソッドには、まだ聞いたことのない特定の名前がありますか?