[注:私のNinjectDependencyResolverクラスはこの質問の一番下にあります。]
設定:
ASP.NET MVC 4アプリには、サービスを利用するコントローラーがあります。
各サービスには、コンストラクターパラメーターとしてIUnitOfWorkインターフェイスがあります。例えば:
public ClientService(IUnitOfWork uow){ //... }
適切に記述されたNinjectDependencyResolver : IDependencyResolver
クラスをGlobal.asax.csクラスに登録すると、これらのサービスが適切にインスタンス化され、すべてが機能するようになります。ここまでは順調ですね。
ただし、属性など、他のコードでサービスをインスタンス化する必要がある場合があります。例えば:
namespace MyApp.Domain.Attributes
{
public class AuthorizeUnprocessedOnlyAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool isUnprocessed = false;
string usuario = string.Empty;
if (httpContext.User.Identity.IsAuthenticated)
{
// THIS IS THE LINE WHERE DI IS NEEDED!!
ClientService service = new ClientService();
usuario = httpContext.User.Identity.Name;
isUnprocessed = service.IsUnprocessed(usuario);
}
return isUnprocessed;
}
}
}
私の問題は次の行です。
ClientService service = new ClientService();
次のように、ClientServiceにパラメーターなしのコンストラクターを指定する必要がありました。
public ClientService() : this (new UnitOfWork()) {}
これは完全に反DIのようです。
これを行う理由は、属性コードに依存関係を挿入する方法がわからないためです。コントローラーはControllerFactoryによってインスタンス化されるので、私はそれについて知らずに通り抜けました。
つまり、NinjectまたはIDependencyResolverについて十分に知りません...
質問1:
では、どうすれば自分より上に上がることができ'Ignorance Pattern'
ますか?
ClientServiceオブジェクトを次の行に沿って取得する必要があります。
NinjectDependencyResolver ndr = new NinjectDependencyResolver();
IUnitOfWorkMR uow = ndr.Kernel.Get<IUnitOfWorkMR>();
IClientService service = new ClientService(uow);
この最初の質問に対する答えが「はい」であっても、私はあまり幸せではありません。
ClientServiceのインスタンスをインスタンス化する必要があるため、IClientServiceインターフェイスをNinjectDependencyResolverクラスで適切に構築されたClientServiceインスタンスにバインドする必要があります。
これはどうしたらいいかわからないので、これが私の2番目の質問です。
質問2:
ClientServiceを適切にインスタンス化するために、IUnitOfWork構築パラメーターの依存性注入をデイジーチェーン接続するにはどうすればよいですか?(以下のコメントアウトされた取り組みを参照してください-私には意味がないのでコメントアウトしました-UnitOfWorkの新しいインスタンスを作成するべきではありませんか?):
NinjectDependencyResolverクラス:
namespace MyApp.Domain.Infrastructure
{
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
public IBindingToSyntax<T> Bind<T>()
{
return kernel.Bind<T>();
}
public IKernel Kernel
{
get { return kernel; }
}
private void AddBindings()
{
kernel.Bind<IUnitOfWorkMR>().To<UnitOfWorkMR>().InRequestScope();
// kernel.Bind<IClientService>().To<ClientService>().WithConstructorArgument("uow", new UnitOfWork());
}
}
}
ノート:
WithConstructorArgumentのエラーを修正しました(パラメーター名がありませんでした)。
編集:
テストでは、信じられないほどのことが起こりました。問題のコードは機能します。質問2に関しては、NinjectDepenedencyResolverクラスの次の変更により、動作中のアプリが突然解き放たれました(このようなことは確かにまれな喜びです)。
kernel.Bind<IUnitOfWorkMR>().To<UnitOfWorkMR>().InRequestScope();
kernel.Bind<IClientService>().To<ClientService>().InRequestScope();
つまり、WithConstructorArgument呼び出しを削除しました。おそらく、NinjectにはUnitOfWorkの動作インスタンスがあり、それを使用してサービスをインスタンス化します。したがって、パラメータのないコンストラクタはもうありません...
しかし、これはRWTDI(それを行う正しい方法)ですか?