1

创建新项目时,将表单信息从表单发回控制器时,它表示不能找到无参数的构造函数。这是预期的,因为用作视图模型的视图模型取决于域模型对象。何时想通过IModelBinder使用IDependencyResolver?

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

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. 何时使用其中之一?
+0

只需在视图模型中添加一个无斜体构造函数(由于内部DefaultModelBinder使用Activator.CreateInstance来初始化您的视图模型的实例,但它不能除非它具有无斜构造函数的构造函数,所以抛出该错误 – 2015-02-08 21:27:02

+0

是的,我知道这一点,并且已经开始修补了,另外,我讨厌修补我的代码,所以这就是问题的原因,而使用构造函数注入在适当地应用DI时是最好的,如果我使用默认构造函数,我将不得不通过一个新的模型实例,结果,我将紧密耦合代码,这正是要避免的。 – 2015-02-08 21:45:28

+0

如果你有一个无参数的构造函数(除了你的现有的构造函数),你不必去_make它传递一个新的model_实例'DefaultModelBinder'将初始化它并绑定你的va lue – 2015-02-08 21:55:26

回答

2

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

您应该在您的 应用程序中使用依赖性RESERVE吗? 您可能想要从您自己的 应用程序中使用IDependencyResolver。抵制那种诱惑。 依赖关系解析器接口正是MVC需要的 - 而且更多的东西都不是 。它不打算隐藏或替换您的依赖关系 注射容器的传统API。大多数容器都有复杂而有趣的API;实际上,它可能是 ,您可能会根据其提供的API和功能比其他任何原因更多地选择您的容器。

的IDependencyResolver旨在供应依赖于MVC框架,而不是你的应用程序。

IDependencyResolver的实现方式遵循service locator (anti-)pattern

此外,IDependencyResolver不需要使用DI与MVC。更好的选择是使用IControllerFactory将依赖关系注入控制器,并使用其他扩展点(如IModelBinder),使用构造函数注入而不是服务位置。因为你正在做构造函数注入(虽然有些人可能会争辩说模型不应该有依赖关系,但这取决于你的框架设计)。至于使用IModelBinder,你正在使用一个好的做法。

作为开发人员,我们总是倾向于尝试尽可能地推广设计,毕竟这通常是最佳的行动方案。但是,谈到DI时,我们必须与这种冲动作斗争。对于DI,最好让每个类明确地按类型请求它自己的依赖关系,这样就很明显类需要什么功能。服务定位器处于这个范围的另一端 - 这是一个黑盒子的服务,它可能包含或不包含应用程序运行所需的所有类型,并且使应用程序配置更加困难。

+0

我不知道IDependencyResolver使用了服务定位器反模式。感谢这些信息,并向我保证使用IModelBinder。我在我的模型中使用了构造函数注入,因为ViewModel与模型本身交互,所以为了让ViewModel存在,我相信让它依赖于我的模型是有意义的,哪个模型可以包含应用程序必须展示给用户的任何东西。我怀疑的是,内核/容器应该只在组合根目录中使用,我想知道是否将它传递给模型联编程序是好的。 – 2015-02-09 15:05:31

+1

使用内核/容器的方式(几乎)与在IControllerFactory中实现它完全一样。您基本上使用IModelBinder作为抽象工厂来创建您的模型。只要您了解IControllerFactory和IModelBinder是组合根的一部分,并且您不应该在您的应用程序中宽松地注入容器,那就没问题。我发现在容器对象周围进行外观抽象是有帮助的,既可以将应用程序从容器中分离出来,又可以帮助确保容器在应用程序中不被滥用。 – NightOwl888 2015-02-09 15:28:50

+0

我还没有弄清楚'IControllerFactory'和'IModelBinder'都是组合根的一部分。事实上,我在NinjectWebCommon App_Start类的'RegisterServices'中注册了新的模型绑定,所以我希望确保只引用它所属的内核/容器。我会提醒其他项目的精度。 – 2015-02-10 02:55:03