看過前兩篇的朋友想必對Model綁定有個大概的瞭解,然而MVC框架給咱們提供了更高的可擴展性的提供程序編程模式,也就是本篇的主題了,會講解一下Model綁定器提供程序的實現以及解決一下上篇遺留的問題。編程
第一個問題是ModelBinderProviderCollection類型的執行過程?框架
還有個本篇的問題就是一樣的向系統上下文中註冊Model綁定器和Model綁定器提供程序,哪個優先級更高?ide
首先咱們先看一下IModelBinderProvider類型的定義,代碼1-1:。測試
代碼1-1spa
public interface IModelBinderProvider { // 摘要: // 返回指定類型的模型聯編程序。 // // 參數: // modelType: // 模型的類型。 // // 返回結果: // 指定類型的模型聯編程序。 IModelBinder GetBinder(Type modelType); }
在代碼1-1中咱們看出,其中的GetBinder()方法是根據ViewModel的類型來作一些操做,最後返回Model綁定器。如今咱們自定義實現一個Model綁定器提供程序代碼1-2。code
代碼1-2對象
using System.Web.Mvc; using ConsoleApplication2; namespace MvcApplication.Infrastructure { public class MyCustomModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(Type modelType) { if (modelType == null) { throw new ArgumentNullException("modelType"); } if (modelType == typeof(Customer)) { //返回對應Customer類型的Model綁定器 } return null; } } }
在代碼1-2中咱們根據modelType判斷是不是Customer類型,而後返回對應Customer類型的Model綁定器。爲何這裏的實現是空的,由於我想把咱們前面講解過的IoC框架用起來,讓Model綁定器提供程序跟Model綁定器解除耦合,想把IoC框架的應用定義在當前系統的上下文中,咱們看一下代碼實現,代碼1-3。blog
代碼1-3ip
using System.Web.Mvc; using Ninject; using System.ComponentModel; using System.ComponentModel.Design; using MvcApplication.Infrastructure.NinjectControllerPart; namespace MvcApplication { public class MVCSystemContext { private static MVCSystemContext _MVCSystemContext; public static MVCSystemContext Context { get { if (_MVCSystemContext == null) { _MVCSystemContext = new MVCSystemContext(); } return _MVCSystemContext; } } private ServiceContainer _serviceContainer; private MVCSystemContext() { _serviceContainer = new ServiceContainer(); _serviceContainer.AddService(typeof(NinjectController),NinjectController.Instance); } public NinjectController NinjectController { get { return (NinjectController)_serviceContainer.GetService(typeof(NinjectController)); } } } }
代碼1-3當中就是我定義的當前系統上下文了,只不過這個是給本身用的,上下文對象中想必是不會把所用到的全部數據或者是功能都添加在裏面的,只是添加個引用而已,如代碼1-3中的NinjectController屬性,NinjectController屬性對應的類型就是NinjectController類型,NinjectController類型的做用就是提供IoC框架的功能,咱們看一下代碼1-4中對於NinjectController類型的定義。get
代碼1-4
using Ninject; namespace MvcApplication.Infrastructure.NinjectControllerPart { public class NinjectController { private static NinjectController _Instance; public static NinjectController Instance { get { return _Instance = new NinjectController(); } } private IKernel _ninjectKernel; private NinjectController() { _ninjectKernel = new StandardKernel(); } public void AddKernelBind<T, U>()where U:T { _ninjectKernel.Bind<T>().To<U>(); } public T GetValueType<T>(Type keyType) { var valueType = _ninjectKernel.Get(keyType); return (T)valueType; } } }
其中對於Ninject這個IoC框架進行了一個最基礎的功能封裝,有的朋友可能會問爲何不公開個一個屬性,何須這樣畫蛇添足,由於我對Ninject的使用也不是很熟練,對於這部分的封裝我只是讓其簡單的公開了兩個功能,一個是綁定一個是獲取值,這樣讓這部份內容還在個人可控範圍內,若是是公開屬性的話,其餘人的胡亂使用致使錯誤的話是不可控的。
切回主題,這樣基礎定義好了事後,咱們再修改1-2中的代碼,把具體實現給加上,示例代碼1-5所示。
代碼1-5
if (modelType == typeof(Customer)) { //返回對應Customer類型的Model綁定器 return MVCSystemContext.Context.NinjectController.GetValueType<IModelBinder>(typeof(IModelBinder)); }
能夠看到代碼1-5中,根據咱們自定義上下文中的提供的IoC功能獲取到綁定在IoC框架中的值,那麼綁定又是在哪裏呢?跟ASP.NET MVC Model綁定(一)所演示的那樣,仍是在項目的Global.asax文件中的MvcApplication類型的Application_Start()方法中添加如代碼1-6。
代碼1-6
MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>(); ModelBinderProviders.BinderProviders.Add(new MyCustomModelBinderProvider());
代碼1-6分別作了兩個操做,先是把對應Customer類型的Model綁定器註冊到了咱們自定義上下文的IoC中,而後再把針對處理Customer類型的Model綁定器提供程序註冊到系統中。運行結果如圖1.
圖1
其中涉及到全部部分的代碼和ASP.NET MVC Model綁定(一)篇幅中的同樣,因此這裏就沒有列舉了。
在此咱們根據上篇中最後圖2所示的那樣,能夠判斷出ModelBinderProviderCollection類型的執行過程是根據當前ParameterDescriptor類型所提供的Model類型對比咱們註冊到或者是系統默認提供的Model綁定器提供程序集合,若是有是針對ParameterDescriptor類型所提供的Model類型(上述示例中是Customer類型)則會有Model綁定器的返回,而後再根據Model綁定器進行Model綁定。
好了如今第一個問題解決了,來解決第二個問題。來看代碼1-7所示。
代碼1-7
public class MyCustomModelBinder:IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return new Customer() { CustomerID = "010", Name = "測試人員", RegistrationDate = DateTime.Now, Address = new Address() { AddressName = "天空之城" } }; } } public class MyCustomModelBinder_Test : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return new Customer() { CustomerID = "010", Name = "測試人員", RegistrationDate = DateTime.Now, Address = new Address() { AddressName = "這裏是根據Model綁定器綁定執行的Model" } }; } }
看到代碼1-7中的MyCustomModelBinder_Test 類型內部Customer類型實例內部的AddressName值已經更改的和以前的不同了。再看一下注冊端的修改,示例代碼1-8。
代碼1-8
ModelBinders.Binders.Add(typeof(Customer), new Binders.MyCustomModelBinder_Test()); MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>(); ModelBinderProviders.BinderProviders.Add(new MyCustomModelBinderProvider());
代碼1-8中,咱們把新定義的MyCustomModelBinder_Test 類型註冊到了系統的Model綁定器集合中,看一下到底是哪個級別更高一點。
來看運行結果圖2
圖2
看到圖2這個結果,想必已經知道了是哪一個級別更高一點了。
做者:金源
出處:http://www.cnblogs.com/jin-yuan/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面