[注意:我的 NinjectDependencyResolver 类位于此问题的底部。]
设置:
在 ASP.NET MVC 4 应用程序中,我有使用服务的控制器。
每个服务都有一个 IUnitOfWork 接口作为构造函数参数。例如:
public ClientService(IUnitOfWork uow){ //... }
在 Global.asax.cs 类中注册一个适当编写NinjectDependencyResolver : IDependencyResolver
的类允许这些服务正确实例化并且一切正常。到目前为止,一切都很好。
但是,在某些情况下,服务需要在其他一些代码中实例化,例如,在属性中。例如:
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 的了解不够……
问题一:
那么,我怎样才能超越我的'Ignorance Pattern'
?
我应该按照以下方式获取我的 ClientService 对象:
NinjectDependencyResolver ndr = new NinjectDependencyResolver();
IUnitOfWorkMR uow = ndr.Kernel.Get<IUnitOfWorkMR>();
IClientService service = new ClientService(uow);
即使第一个问题的答案是“是”,我也不太高兴:
我仍然需要实例化 ClientService 的实例,所以现在我必须将 IClientService 接口绑定到 NinjectDependencyResolver 类中正确构造的 ClientService 实例。
这个我不知道该怎么做,所以这是我的第二个问题:
问题2:
如何菊花链 IUnitOfWork 构造参数的依赖注入以正确实例化 ClientService?(请参阅下面我注释掉的努力 - 我将其注释掉是因为它对我来说甚至没有意义 - 我不应该创建 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 中的错误(它缺少参数名称)。
编辑:
在测试中,令人难以置信的事情发生了:问题 1 中的代码有效。至于问题 2,NinjectDepenedencyResolver 类中的以下更改突然释放了一个工作应用程序(这样的事情确实很少见):
kernel.Bind<IUnitOfWorkMR>().To<UnitOfWorkMR>().InRequestScope();
kernel.Bind<IClientService>().To<ClientService>().InRequestScope();
即,我删除了 WithConstructorArgument 调用。据推测,Ninject 有一个 UnitOfWork 的工作实例,它使用它来实例化我的服务。所以,没有更多的无参数构造函数......
但这是 RWTDI(正确的方法)吗?