10

我正在 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 的依赖?

4

3 回答 3

7

模型绑定器应该只进行数据转换,不应该依赖任何服务,当然也不应该触发任何数据库通信。这应该在您的应用程序的另一部分完成。您的 Action 方法应该只接受 aGuid userId并且您应该userDataService.GetUser(UserID);从控制器内部(或在较低层,例如,在业务命令内部)调用。通过这样做,您的问题将不存在。

于 2012-06-01T13:02:21.667 回答
5

你可以这样做:

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的观点——为此使用模型活页夹似乎不太正确。相反,您可以将 an 注入ICurrentUserContext到您的控制器中,实现返回当前用户。然后,您甚至不需要向控制器操作添加参数。

于 2012-06-01T14:16:30.413 回答
1

使用DependencyResolver.Current获取您的服务。这实际上比 using 好得多new因为这意味着您没有将该服务与服务类型耦合。您可以稍后决定UserDataService在不更改客户端代码的情况下进行抽象并插入不同的变体,这确实是重点。

此外,DependencyResolver.Current它是一个可设置的IDependencyResolver,因此您可以自己实现该接口,如果您喜欢该框架,则可以使用 Ninject 支持它的类。

在 MVC3 中进行依赖注入的另一种方法是设置你自己的IControllerActivator,如果你愿意,它允许你进行构造函数注入。

于 2012-06-01T12:11:33.093 回答