您好,登錄后才能下訂單哦!
前面的篇幅對(duì)于Model綁定器IModelBinder以及實(shí)現(xiàn)類型、Model綁定器提供程序都作了粗略的講解,可以把Model綁定器想象成一個(gè)大的容器,為什么這么說呢?留個(gè)疑問在這里。
首先控制器的方法參數(shù)可能是很多種類型的、可能是多個(gè)同一種類型的,應(yīng)對(duì)這種情況MVC框架使用的綁定實(shí)現(xiàn)都是IValueProvider來做的,而針對(duì)參數(shù)類型的不同等等一些情況,IValueProvider的實(shí)現(xiàn)類型也是有很大的差異的,這些具體實(shí)現(xiàn)的講解會(huì)在后續(xù)的篇幅中講解。
都說旁觀者清,我們不要走進(jìn)MVC框架,站在外面看。本篇會(huì)已站在外面的角度去對(duì)IValueProvider做個(gè)描述。
IModelBinder、自定義Model綁定器簡(jiǎn)單實(shí)現(xiàn)
Model綁定器在MVC框架中的位置
MVC中的默認(rèn)Model綁定器生成過程
IModelBinderProvider的簡(jiǎn)單應(yīng)用
IValueProvider在MVC框架中生成的位置以及過程
IValueProvider的應(yīng)用場(chǎng)景
IValueProvider的實(shí)現(xiàn)之NameValueCollectionValueProvider
生成的位置
大家可否記得在ASP.NET MVC Model綁定(二)中對(duì)于Model綁定器生成位置的描述,這里借用一下那副描述生成位置的示意圖,
圖1
圖1中所示,藍(lán)色線條執(zhí)行流程中,在Model綁定器生成后,即會(huì)生成IValueProvider類型,說是生成有點(diǎn)不妥,改成獲取吧。為什么這樣說在下面的生成部分會(huì)講到
生成的過程
我們先看一下圖1中藍(lán)色線條流程的實(shí)現(xiàn)代碼。
代碼1-1
protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) { Type parameterType = parameterDescriptor.ParameterType; IModelBinder modelBinder = this.GetModelBinder(parameterDescriptor); IValueProvider valueProvider = controllerContext.Controller.ValueProvider; string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor); ModelBindingContext context2 = new ModelBindingContext { FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null, ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType), ModelName = str, ModelState = controllerContext.Controller.ViewData.ModelState, PropertyFilter = propertyFilter, ValueProvider = valueProvider }; ModelBindingContext bindingContext = context2; return (modelBinder.BindModel(controllerContext, bindingContext) ?? parameterDescriptor.DefaultValue); }
對(duì)于代碼1-1中所示的方法,不用去管的它的返回類型以及這個(gè)方法的作用,我們現(xiàn)在想知道的就是IValueProvider是怎么來的!?。?/p>
從代碼1-1中,我們可以明確的看到在生成Model綁定器過后,MVC框架從ControllerContext控制器上下文參數(shù)對(duì)象中獲得了當(dāng)前請(qǐng)求所請(qǐng)求的控制器的引用,然后根據(jù)當(dāng)前的控制器對(duì)象引用獲取到IValueProvider類型。
然后MVC框架會(huì)實(shí)例化ModelBindingContext類型,并且把剛剛獲取的IValueProvider類型賦值到其中的ValueProvider屬性上。
對(duì)于ModelBindingContext類型,Model綁定上下文對(duì)象,看下它的定義代碼1-2。
代碼1-2
public class ModelBindingContext { public ModelBindingContext(); public ModelBindingContext(ModelBindingContext bindingContext); public bool FallbackToEmptyPrefix { get; set; } public object Model { get; set; } public ModelMetadata ModelMetadata { get; set; } public string ModelName { get; set; } public ModelStateDictionary ModelState { get; set; } public Type ModelType { get; set; } public Predicate<string> PropertyFilter { get; set; } public IDictionary<string, ModelMetadata> PropertyMetadata { get; } // // 摘要: // 獲取或設(shè)置值提供程序。 // // 返回結(jié)果: // 值提供程序。 public IValueProvider ValueProvider { get; set; } }
這里我們只需初步的了解ModelBindingContext類型就行了,回到主題中,上面說到從當(dāng)前控制器對(duì)象的引用中直接獲取的,那我們就去看一下控制器中的ValueProvider屬性。我們就來看一下Controller類型,代碼1-3.
代碼1-3
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter { …… }
跟大家開了個(gè)玩笑,緩解下氣氛。Controller類型中并沒有我們所要找的屬性,有的朋友想到了,對(duì)的是在基類類型中的,確實(shí)是在ControllerBase類型中的(代碼1-4)。
代碼1-4
public abstract class ControllerBase : IController { …… public IValueProvider ValueProvider { get; set; } }
難道我們?cè)谑褂肐ValueProvider的時(shí)候是要賦值到控制器對(duì)象上的嗎?
當(dāng)然不是了,我們看一下代碼1-4中ValueProvider屬性的實(shí)現(xiàn),示例代碼1-5.
代碼1-5
public IValueProvider ValueProvider { get { if (this._valueProvider == null) { this._valueProvider = ValueProviderFactories.Factories.GetValueProvider(this.ControllerContext); } return this._valueProvider; } set { this._valueProvider = value; } }
看到這里想必大家就應(yīng)該已經(jīng)了解了IValueProvider類型的由來了,是從系統(tǒng)的ValueProviderFactories類型的Factories屬性中來根據(jù)當(dāng)前控制器上下文獲取到的。
這里我們看一下生成IValueProvider類型的幾個(gè)相關(guān)類型的定義,示例代碼1-6。
代碼1-6
public static class ValueProviderFactories { // 摘要: // 獲取應(yīng)用程序的值提供程序工廠的集合。 // // 返回結(jié)果: // 值提供程序工廠對(duì)象的集合。 public static ValueProviderFactoryCollection Factories { get; } } public class ValueProviderFactoryCollection : Collection<ValueProviderFactory> { public ValueProviderFactoryCollection(); public ValueProviderFactoryCollection(IList<ValueProviderFactory> list); // 摘要: // 為指定控制器上下文返回值提供程序工廠。 // // 參數(shù): // controllerContext: // 一個(gè)對(duì)象,該對(duì)象封裝有關(guān)當(dāng)前 HTTP 請(qǐng)求的信息。 // // 返回結(jié)果: // 用于指定控制器上下文的值提供程序工廠對(duì)象。 public IValueProvider GetValueProvider(ControllerContext controllerContext); protected override void InsertItem(int index, ValueProviderFactory item); protected override void SetItem(int index, ValueProviderFactory item); } public abstract class ValueProviderFactory { protected ValueProviderFactory(); // 摘要: // 為指定控制器上下文返回值提供程序?qū)ο蟆? // // 參數(shù): // controllerContext: // 一個(gè)對(duì)象,該對(duì)象封裝有關(guān)當(dāng)前 HTTP 請(qǐng)求的信息。 // // 返回結(jié)果: // 值提供程序?qū)ο蟆? public abstract IValueProvider GetValueProvider(ControllerContext controllerContext); }
ValueProviderFactories類型的這種模式前面見過太多了,就不說了,它里面包含著ValueProviderFactoryCollection類型的靜態(tài)屬性,而ValueProviderFactoryCollection類型又是ValueProviderFactory類型的集合類型,所以在最終生成IValueProvider類型的時(shí)候也是先遍歷ValueProviderFactoryCollection類型,獲取每個(gè)ValueProviderFactory類型的實(shí)例并且來生成IValueProvider類型,這里也是最先匹配而不是最優(yōu)匹配。
這里捎帶一句,可以用控制器上下文對(duì)象來對(duì)ValueProviderFactory類型中的生成邏輯進(jìn)行分類,針對(duì)不同的控制器生成不同的IValueProvider類型。對(duì)于IValueProvider類型的使用后面篇幅會(huì)有說明。
免責(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)容。