2

在我的MVC 4項目,我有一個模型,如:ModelFactory爲MVC 4使用Unity

public class MyModel 
{ 
    private readonly IService MyService; 

    public MyModel([Dependency]IService service) 
    { 
     this.MyService = service; 
    } 
    // ... 
} 

我的控制器有一個行動,這是一個HttpPost這樣的:

[HttpPost] 
public ActionResult Show(MyModel myModel) 
{ 
    // do stuff 

我的控制器不(也不應該)有我的IoC容器的一個實例。 當HttpPost發生並且調用操作時,MVC會在模型綁定時嘗試創建我的模型的實例。它需要一個無參數的構造函數來完成。如果它使用默認構造函數創建模型,則不會設置MyService,並且該模型不會具有其存在的所有依賴關係。我不想調用myModel.Init(someIServiceInstance)。我想插入框架,以便在創建模型時解析依賴關係(調用正確的構造函數)。

我目前使用Unity作爲我的依賴解析器,並且有幾個工廠用於控制器,服務客戶端等。對於控制器,我能夠註冊ControllerFactory並將依賴關係傳遞給控制器​​,但我不看不到我可以註冊的ModelFactory。我不太關心綁定過程本身;一旦模型被實例化,我很滿意綁定是如何完成的。我只想實現模型的創建/構造方式。如果ModelFactory使用對容器的引用來解析依賴關係(我可以將容器作爲參數注入到構造函數中,我不希望控制器直接引用容器)。

有沒有人有ModelFactory(或ModelBinder,和/或ModelBinderResolver等)的樣本來處理Model的創建,然後依靠框架實現來完成Binding過程的其餘部分?

回答

4

你可以寫一個自定義的模型綁定:

public class MyModelModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     // TODO: create the model instance here using your DI framework or the 
     // DependencyResolver which is more correct 
    } 
} 

,然後在Global.asax註冊此模型綁定:

ModelBinders.Binders.Add(typeof(MyModel), new MyModelModelBinder()); 

但通常這是不好的做法。我建議你使用視圖模型,並讓你的控制器操作將視圖模型作爲參數,並將視圖模型傳遞給視圖。那些視圖模型將具有無參數的構造函數。然後,您可以將您的域模型或存儲庫注入到控制器構造函數中。

+0

由於某種原因,這並沒有顯示出來直到我發佈我的答案之後。謝謝! – DaveH

2

我想我想通了:

public class MyModelBinder : DefaultModelBinder 
{ 
    private readonly UnityContainer container; 

    public MyModelBinder(UnityContainer container) 
    { 
     this.container = container; 
    } 

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     if (modelType == null) 
     { 
      return base.CreateModel(controllerContext, bindingContext, null); 
     } 

     return this.container.Resolve(modelType); 
    } 
} 

而且在Global.asax中,內部的Application_Start(),或在你的IoC配置:

ModelBinders.Binders.Add(typeof(object), new MyModelBinder(container)); 
+1

我實際上注意到,爲typeof(object)添加一個Binder並不起作用,即使在首先調用了binder上的Clear時也是如此。但是,我確實創建了IModelBinderProvinder的實現。它返回MyModelBinder。我還創建了ModelFactory,現在控制器將ModelFactory作爲構造函數中的依賴項。該模型將IService作爲它的構造函數中的依賴項。始終返回MyModelBinder的ModelBinderProvider在Application_Start中註冊。 MyModelBinder對ModelFactory也有依賴關係,通過構造函數解析。 – DaveH

+1

直接使用DefaultModelBinder而不是IModelBinder接口看起來好像少得多,感謝指針@DaveH。 –