1

在创建新项目时,当将信息从表单发送回控制器时,它表示找不到无参数构造函数。这是意料之中的,因为用作视图模型的视图模型取决于域模型对象。

然后我决定编写自己的模型活页夹。

NewItemViewModelBinder

public class NewItemViewModelBinder : DefaultModelBinder {
    public NewItemViewModelBinder(IKernel kernel) {
        if (kernel == null) throw new ArgumentNullException("kernel");
        this.kernel = kernel;
    }

    protected override object CreateModel(ControllerContext controllerContext
        , ModelBindingContext bindingContext, Type modelType) {
        return kernel.Get(modelType);
    }

    private readonly IKernel kernel;
}

这个带有模型绑定器的解决方案在将这个绑定器注册到 NinjectWebCommon.RegisterServices 方法中的 ModelBinders.Binders 后工作得很好。

public void RegisterServices(IKernel kernel) {
    CompositionRoot.ComposeObjectGraph();
    ModelBinders
        .Binders
        .Add(typeof(NewItemViewModel), new NewItemViewModelBinder(kernel));
}

此外,我还看到了其他一些关于 DependencyResolver 的帖子。所以我想如果我能写一个依赖解析器来解决所有其他的创建问题,那么剩下的我就没有麻烦了。

NinjectDependencyResolver

public class NinjectDependencyResolver : NinjectDependencyScope
    : System.Web.Http.Dependencies.IDependencyResolver
    , System.Web.Mvc.IDependencyResolver {
    public NinjectDepencyResolver(IKernel kernel
        , IDependencyScopeFactory factory) : base(kernel) {
        if (kernel == null) throw new ArgumentNullException("kernel");
        if (factory == null) throw new ArgumentNullException("factory");
        this.kernel = kernel;
    }

    public IDependencyScope BeginScope() { 
        return factory.Create(kernel.BeginBlock()); 
    }

    public object GetService(Type serviceType) {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        return kernel.GetAll(serviceType);
    }

    public void Dispose() { base.Dispose(); }

    private readonly IKernel kernel;
    private readonly IDependencyScopeFactory factory;
}

在将这个新的解析器设置为 MVC 的依赖解析器之后,

DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));

它不起作用,我遇到了与无参数构造函数相同的问题。

所以,我有三个问题。

  1. 我在 DependencyResolver 方法上做错了什么?
  2. 与 DependencyResolver 相比,使用 ModelBinder 有什么好处?
  3. 什么时候使用其中一个?
4

1 回答 1

2

根据Wrox Professional ASP.NET MVC 4,第 308 页,您不应将 IDependencyResolver 用于您的应用程序。

您应该在您的应用程序中使用依赖解析器吗?您可能很想从自己的应用程序中使用 IDependencyResolver。抵制这种诱惑。依赖解析器接口正是 MVC 所需要的——仅此而已。它并不打算隐藏或替换依赖注入容器的传统 API。大多数容器都有复杂而有趣的 API;事实上,您很可能会根据它提供的 API 和特性来选择您的容器,而不是其他任何原因。

IDependencyResolver 旨在为MVC 框架提供依赖项,而不是为您的应用程序提供依赖项。

IDependencyResolver 的实现方式遵循服务定位器(反)模式

此外,IDependencyResolver 不需要将 DI 与 MVC 一起使用。更好的选择是使用 IControllerFactory 将依赖项注入控制器并使用其他扩展点(例如 IModelBinder),使用构造函数注入,而不是服务位置。

至于使用 IModelBinder,您在示例中使用了一个很好的做法,因为您正在执行构造函数注入(尽管有些人可能会争辩说模型不应该有依赖关系,但这取决于您的框架设计)。

作为开发人员,我们总是倾向于尽可能地概括设计,毕竟这通常是最好的做法。然而,当谈到 DI 时,我们必须与这种冲动作斗争。对于 DI,最好让每个类按类型明确要求其自己的依赖项,这样一个类需要什么才能运行是显而易见的。服务定位器在这个范围的另一端——它是一个服务的黑盒,可能包含也可能不包含应用程序运行所需的所有类型,它使应用程序更难配置。

于 2015-02-08T22:05:45.907 回答