我正在使用MVC3网站,试图使用Ninject来解决我的依赖关系。我有以下情况:
public class UserModelBinder : IModelBinder
{
//[Inject]
public UserDataService userData { get; set; }
public object BindModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
Guid UserID =
(Guid)Membership.GetUser().ProviderUserKey;
//userDataService = DependencyResolver.Current
// .GetService<UserDataService>();
User user = userDataService.GetUser(UserID);
return user;
}
}
注意到注释的代码行?
我在Global.asax
注册了
ModelBinders.Binders[typeof(User)] = new UserModelBinder();
所以我无法通过施工来注射。
UserDataService
有一系列依赖项:UserDataService -> UserRepository -> Context
。所以在这里使用Ninject会很好。
问题是,当我取消注释[Inject]
以上userData
声明,并尝试让Ninject将对象作为参数注入时,由于某种原因它不起作用:我得到空引用异常。
(可能是UserDataService
没有接口而且我将对象绑定到自身:kernel.Bind<UserDataService>().ToSelf();
?? )
我在代码中有另一个注释行:
userDataService = DependencyResolver.Current
.GetService<UserDataService>();
如果取消注释,设置工作,我会插入正确的对象,但现在我们依赖于DependencyResolver,这并不比说userDataService = new UserDataService()
我错过了什么吗?是否有另一种方法将对象作为参数注入,而不是引入对Ninject或DependencyResolver的依赖?
答案 0 :(得分:6)
模型绑定器应该只进行数据转换,不应该依赖任何服务,当然也不会触发任何数据库通信。这应该在您的应用程序的另一部分中完成。您的Action方法应该只需Guid userId
,您应该从控制器中调用userDataService.GetUser(UserID);
(或在较低层,例如business command内)。通过这样做,您的问题将不存在。
答案 1 :(得分:4)
你可以这样做:
public class UserModelBinder : IModelBinder
{
public Func<UserDataService> UserData { get; set; }
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Guid UserID = (Guid)Membership.GetUser().ProviderUserKey;
User u = UserData().GetUser(UserID);
return u;
}
}
然后当你连线时:
ModelBinders.Binders[typeof(User)] = new UserModelBinder()
{
userData = () => DependencyResolver.Current.GetService<UserDataService>();
}
好处是您的UserModelBinder
不知道正在使用容器,同时仍然可以打开注射。
但我同意Steven - 使用模型绑定器这似乎不太合适。相反,您可以将ICurrentUserContext
注入控制器,其中实现返回当前用户。然后,您甚至不需要在控制器操作中添加参数。
答案 2 :(得分:1)
使用DependencyResolver.Current
获取您的服务。这实际上很多比使用new
更好,因为这意味着您没有将该服务与服务类型相结合。您可以稍后决定使UserDataService
成为抽象并插入不同的变体而不更改您的客户端代码,这真的是重点。
此外,DependencyResolver.Current
是一个可设置的IDependencyResolver
,因此您可以自己实现该接口,如果您喜欢该框架,可以使用Ninject支持它。
在MVC3中进行依赖注入的另一种方法是设置自己的IControllerActivator
,如果你愿意的话,它允许你进行构造函数注入。