看過前兩篇的朋友想必對Model綁定有個大概的了解,然而MVC框架給我們提供了更高的可擴展性的提供程序編程模式,也就是本篇的主題了,會講解一下Model綁定器提供程序的實現以及解決一下上篇遺留的問題。
第一個問題是ModelBinderProviderCollection類型的執行過程?
還有個本篇的問題就是同樣的向系統上下文中注冊Model綁定器和Model綁定器提供程序,哪一個優先級更高?
IModelBinder、自定義Model綁定器簡單實現
Model綁定器在MVC框架中的位置
MVC中的默認Model綁定器生成過程
IModelBinderProvider的簡單應用
IValueProvider在MVC框架中生成的位置以及過程
IValueProvider的應用場景
IValueProvider的實現之NameValueCollectionValueProvider
首先我們先看一下IModelBinderProvider類型的定義,代碼1-1:。
代碼1-1
public interface IModelBinderProvider
{
// 摘要:
// 返回指定類型的模型聯編程序。
//
// 參數:
// modelType:
// 模型的類型。
//
// 返回結果:
// 指定類型的模型聯編程序。
IModelBinder GetBinder(Type modelType);
}在代碼1-1中我們看出,其中的GetBinder()方法是根據ViewModel的類型來做一些操作,最后返回Model綁定器?,F在我們自定義實現一個Model綁定器提供程序代碼1-2。
代碼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。
代碼1-3
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類型的定義。
代碼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這個結果,想必已經知道了是哪個級別更高一點了。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。