您好,登錄后才能下訂單哦!
看過(guò)前兩篇的朋友想必對(duì)Model綁定有個(gè)大概的了解,然而MVC框架給我們提供了更高的可擴(kuò)展性的提供程序編程模式,也就是本篇的主題了,會(huì)講解一下Model綁定器提供程序的實(shí)現(xiàn)以及解決一下上篇遺留的問(wèn)題。
第一個(gè)問(wèn)題是ModelBinderProviderCollection類(lèi)型的執(zhí)行過(guò)程?
還有個(gè)本篇的問(wèn)題就是同樣的向系統(tǒng)上下文中注冊(cè)Model綁定器和Model綁定器提供程序,哪一個(gè)優(yōu)先級(jí)更高?
IModelBinder、自定義Model綁定器簡(jiǎn)單實(shí)現(xiàn)
Model綁定器在MVC框架中的位置
MVC中的默認(rèn)Model綁定器生成過(guò)程
IModelBinderProvider的簡(jiǎn)單應(yīng)用
IValueProvider在MVC框架中生成的位置以及過(guò)程
IValueProvider的應(yīng)用場(chǎng)景
IValueProvider的實(shí)現(xiàn)之NameValueCollectionValueProvider
首先我們先看一下IModelBinderProvider類(lèi)型的定義,代碼1-1:。
代碼1-1
public interface IModelBinderProvider { // 摘要: // 返回指定類(lèi)型的模型聯(lián)編程序。 // // 參數(shù): // modelType: // 模型的類(lèi)型。 // // 返回結(jié)果: // 指定類(lèi)型的模型聯(lián)編程序。 IModelBinder GetBinder(Type modelType); }
在代碼1-1中我們看出,其中的GetBinder()方法是根據(jù)ViewModel的類(lèi)型來(lái)做一些操作,最后返回Model綁定器?,F(xiàn)在我們自定義實(shí)現(xiàn)一個(gè)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)) { //返回對(duì)應(yīng)Customer類(lèi)型的Model綁定器 } return null; } } }
在代碼1-2中我們根據(jù)modelType判斷是否是Customer類(lèi)型,然后返回對(duì)應(yīng)Customer類(lèi)型的Model綁定器。為什么這里的實(shí)現(xiàn)是空的,因?yàn)槲蚁氚盐覀兦懊嬷v解過(guò)的IoC框架用起來(lái),讓Model綁定器提供程序跟Model綁定器解除耦合,想把IoC框架的應(yīng)用定義在當(dāng)前系統(tǒng)的上下文中,我們看一下代碼實(shí)現(xiàn),代碼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當(dāng)中就是我定義的當(dāng)前系統(tǒng)上下文了,只不過(guò)這個(gè)是給自己用的,上下文對(duì)象中想必是不會(huì)把所用到的所有數(shù)據(jù)或者是功能都添加在里面的,只是添加個(gè)引用而已,如代碼1-3中的NinjectController屬性,NinjectController屬性對(duì)應(yīng)的類(lèi)型就是NinjectController類(lèi)型,NinjectController類(lèi)型的作用就是提供IoC框架的功能,我們看一下代碼1-4中對(duì)于NinjectController類(lèi)型的定義。
代碼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; } } }
其中對(duì)于Ninject這個(gè)IoC框架進(jìn)行了一個(gè)最基礎(chǔ)的功能封裝,有的朋友可能會(huì)問(wèn)為什么不公開(kāi)個(gè)一個(gè)屬性,何必這樣多此一舉,因?yàn)槲覍?duì)Ninject的使用也不是很熟練,對(duì)于這部分的封裝我只是讓其簡(jiǎn)單的公開(kāi)了兩個(gè)功能,一個(gè)是綁定一個(gè)是獲取值,這樣讓這部分內(nèi)容還在我的可控范圍內(nèi),如果是公開(kāi)屬性的話(huà),其他人的胡亂使用導(dǎo)致錯(cuò)誤的話(huà)是不可控的。
切回主題,這樣基礎(chǔ)定義好了過(guò)后,我們?cè)傩薷?-2中的代碼,把具體實(shí)現(xiàn)給加上,示例代碼1-5所示。
代碼1-5
if (modelType == typeof(Customer)) { //返回對(duì)應(yīng)Customer類(lèi)型的Model綁定器 return MVCSystemContext.Context.NinjectController.GetValueType<IModelBinder>(typeof(IModelBinder)); }
可以看到代碼1-5中,根據(jù)我們自定義上下文中的提供的IoC功能獲取到綁定在IoC框架中的值,那么綁定又是在哪里呢?跟ASP.NET MVC Model綁定(一)所演示的那樣,還是在項(xiàng)目的Global.asax文件中的MvcApplication類(lèi)型的Application_Start()方法中添加如代碼1-6。
代碼1-6
MVCSystemContext.Context.NinjectController.AddKernelBind<IModelBinder, Binders.MyCustomModelBinder>(); ModelBinderProviders.BinderProviders.Add(new MyCustomModelBinderProvider());
代碼1-6分別做了兩個(gè)操作,先是把對(duì)應(yīng)Customer類(lèi)型的Model綁定器注冊(cè)到了我們自定義上下文的IoC中,然后再把針對(duì)處理Customer類(lèi)型的Model綁定器提供程序注冊(cè)到系統(tǒng)中。運(yùn)行結(jié)果如圖1.
圖1
其中涉及到所有部分的代碼和ASP.NET MVC Model綁定(一)篇幅中的一樣,所以這里就沒(méi)有列舉了。
在此我們根據(jù)上篇中最后圖2所示的那樣,可以判斷出ModelBinderProviderCollection類(lèi)型的執(zhí)行過(guò)程是根據(jù)當(dāng)前ParameterDescriptor類(lèi)型所提供的Model類(lèi)型對(duì)比我們注冊(cè)到或者是系統(tǒng)默認(rèn)提供的Model綁定器提供程序集合,如果有是針對(duì)ParameterDescriptor類(lèi)型所提供的Model類(lèi)型(上述示例中是Customer類(lèi)型)則會(huì)有Model綁定器的返回,然后再根據(jù)Model綁定器進(jìn)行Model綁定。
好了現(xiàn)在第一個(gè)問(wèn)題解決了,來(lái)解決第二個(gè)問(wèn)題。來(lái)看代碼1-7所示。
代碼1-7
public class MyCustomModelBinder:IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return new Customer() { CustomerID = "010", Name = "測(cè)試人員", 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 = "測(cè)試人員", RegistrationDate = DateTime.Now, Address = new Address() { AddressName = "這里是根據(jù)Model綁定器綁定執(zhí)行的Model" } }; } }
看到代碼1-7中的MyCustomModelBinder_Test 類(lèi)型內(nèi)部Customer類(lèi)型實(shí)例內(nèi)部的AddressName值已經(jīng)更改的和之前的不一樣了。再看一***冊(cè)端的修改,示例代碼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 類(lèi)型注冊(cè)到了系統(tǒng)的Model綁定器集合中,看一下究竟是哪一個(gè)級(jí)別更高一點(diǎn)。
來(lái)看運(yùn)行結(jié)果圖2
圖2
看到圖2這個(gè)結(jié)果,想必已經(jīng)知道了是哪個(gè)級(jí)別更高一點(diǎn)了。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。