C# DI-创建服务对象
[注意:我的NinjectDependencyResolver类位于此问题的底部。] 设置: 在ASP.NETMVC4应用程序中,我有使用服务的控制器 每个服务都有一个IUnitOfWork接口作为构造函数参数。例如:C# DI-创建服务对象,c#,asp.net-mvc-4,ninject,C#,Asp.net Mvc 4,Ninject,[注意:我的NinjectDependencyResolver类位于此问题的底部。] 设置: 在ASP.NETMVC4应用程序中,我有使用服务的控制器 每个服务都有一个IUnitOfWork接口作为构造函数参数。例如: public ClientService(IUnitOfWork uow){ //... } 在Global.asax.cs类中注册一个适当编写的NinjectDependencyResolver:IDependencyResolver类,可以正确实例化这些服务并使所有工作正常
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了解不够
问题1:
那么,我怎样才能超越我的“无知模式”
我应该按照以下方式获取ClientService对象:
NinjectDependencyResolver ndr = new NinjectDependencyResolver();
IUnitOfWorkMR uow = ndr.Kernel.Get<IUnitOfWorkMR>();
IClientService service = new ClientService(uow);
NinjectDependencyResolver ndr=新的NinjectDependencyResolver();
IUnitOfWorkMR uow=ndr.Kernel.Get();
IClientService服务=新客户端服务(uow);
即使第一个问题的答案是“是”,我也不太高兴:
我仍然需要实例化ClientService的实例,因此现在我必须将IClientService接口绑定到NinjectDependencyResolver类中正确构造的ClientService实例
这我不知道怎么做,所以这是我的第二个问题:
问题2:
如何通过菊花链将IUnitoWork构造参数的依赖项注入连接起来,以正确实例化ClientService?(请参见下面我的注释-我注释了它,因为它对我来说根本没有意义-我不应该创建UnitOfWork的新实例,是吗?)
NinjectDependencyResolver类:
名称空间MyApp.Domain.Infrastructure
{
公共类NinjectDependencyResolver:IDependencyResolver
{
私有IKernel内核;
公共NinjectDependencyResolver()
{
内核=新的标准内核();
AddBindings();
}
公共对象GetService(类型serviceType)
{
返回kernel.TryGet(serviceType);
}
公共IEnumerable GetServices(类型serviceType)
{
返回kernel.GetAll(serviceType);
}
公共IBindingToSyntax绑定()
{
返回kernel.Bind();
}
公共IKernel核
{
获取{返回内核;}
}
私有void AddBindings()
{
kernel.Bind().To().InRequestScope();
//kernel.Bind().To().WithConstructorArgument(“uow”,newUnitOfWork());
}
}
}
注:
我已经更正了WithConstructorArgument中的错误(缺少参数名)
编辑:
在测试中,不可思议的事情发生了:问题1中的代码可以工作。至于问题2,NinjectDependedEncyResolver类中的以下更改突然释放了一个可用的应用程序(这些事情确实是罕见的乐趣):
kernel.Bind().To().InRequestScope();
kernel.Bind().To().InRequestScope();
也就是说,我删除了WithConstructorArgument调用。Ninject大概有一个UnitOfWork的工作实例,它使用它来实例化我的服务。所以,不再有无参数构造函数
但是这是RWTDI(正确的方法)吗?是的,这是配置绑定的正确方法。这就是DI容器的全部要点,它根据构造函数的参数和配置确定要注入什么 然而,我发现你的NinjectDependcyResolver很奇怪。为什么不直接使用Ninject.MVC3呢?(它也适用于MVC4)。这将自动为MVC设置DependencyResolver,您将在App_Start\njectWebCommon.cs中配置映射 对于属性,正确的方法是使用随Ninject.MVC3自动安装的BindFilter扩展。您可以这样配置它:
kernel.BindFilter<MyAuthorization>(FilterScope.Action, 0)
.WhenActionMethodHas<MyAuthorization>();
var x = DependencyResolver.Current.GetService<MyType>();
kernel.BindFilter(FilterScope.Action,0)
.WhenActionMethodHas();
然后Ninject将自动处理注入其中的任何配置对象
这就消除了从属性内部调用GetService的需要(这总是一种代码味道),并使所有内容都能协同工作
至少,使用Ninject.MVC3来设置您的MVC应用程序,然后在过滤器中,如果您真的想调用GetService,那么使用MVC DependencyResolver(Ninject.MVC自动向其注册)并执行以下操作:
kernel.BindFilter<MyAuthorization>(FilterScope.Action, 0)
.WhenActionMethodHas<MyAuthorization>();
var x = DependencyResolver.Current.GetService<MyType>();
var x=DependencyResolver.Current.GetService();
但同样,您应该真正使用BindFilter语法。事实上,问题1中的代码似乎运行良好,有效的方法是按照NinjectDependencyResolver类中的要求绑定每个服务或类,而不指定UnitOfWork参数,大概是因为Ninject已经实例化并处理了这个问题。细节上仍然有点模糊,但是,嘿,什么有效,为什么要改变它?我在问题中添加了一个编辑。我在跟踪史蒂夫·桑德森和亚当·弗里曼。我将按照您的建议,切换到Ninject.MVC3。我们一定会看看BindFilter语法。非常感谢您的详细答复。