在ASP.NET MVC3模型绑定器中使用依赖注入

tra*_*max 10 .net c# asp.net-mvc dependency-injection ninject

我正在使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意到注释的代码行?

我确实将活页夹注册Global.asax

ModelBinders.Binders[typeof(User)] = new UserModelBinder();
Run Code Online (Sandbox Code Playgroud)

所以我不能真正通过施工注射.

UserDataService有一连串的依赖:UserDataService -> UserRepository -> Context.所以在这里使用Ninject会很好.

问题是,当我取消注释[Inject]上面的userData声明,并尝试让Ninject注入对象作为参数时,它由于某种原因不起作用:我得到空引用异常.

(可能是UserDataService没有接口,我将对象绑定到自身:kernel.Bind<UserDataService>().ToSelf();??)

我在代码中有另一个注释行:

userDataService = DependencyResolver.Current
    .GetService<UserDataService>();
Run Code Online (Sandbox Code Playgroud)

如果取消注释,设置工作,我会插入正确的对象,但现在我们依赖DependencyResolver,这并不比说 userDataService = new UserDataService()

我错过了什么吗?是否有另一种方法将对象作为参数注入,而不是引入对Ninject或DependencyResolver的依赖?

Ste*_*ven 7

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

  • 模型绑定器创建类型实例,创建的子类型可能取决于您绑定的项目的类型.因此,如果您只有一个密钥,那么您需要查找可能在数据库中的类型! (4认同)

Pau*_*ell 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当您将其连接时:

ModelBinders.Binders[typeof(User)] = new UserModelBinder() 
{  
    userData = () => DependencyResolver.Current.GetService<UserDataService>();
}
Run Code Online (Sandbox Code Playgroud)

好处是您UserModelBinder不知道正在使用容器,而仍可打开进行注射。

但是我同意史蒂文 -为此使用模型绑定器似乎不太正确。相反,您可以将注入ICurrentUserContext到您的控制器中,其中实现将返回当前用户。然后,您甚至无需在控制器操作中添加参数。