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