前面的篇幅對于Model綁定器IModelBinder以及實現類型、Model綁定器提供程序都作了粗略的講解,可以把Model綁定器想象成一個大的容器,為什么這么說呢?留個疑問在這里。

首先控制器的方法參數可能是很多種類型的、可能是多個同一種類型的,應對這種情況MVC框架使用的綁定實現都是IValueProvider來做的,而針對參數類型的不同等等一些情況,IValueProvider的實現類型也是有很大的差異的,這些具體實現的講解會在后續的篇幅中講解。
都說旁觀者清,我們不要走進MVC框架,站在外面看。本篇會已站在外面的角度去對IValueProvider做個描述。
IModelBinder、自定義Model綁定器簡單實現
Model綁定器在MVC框架中的位置
MVC中的默認Model綁定器生成過程
IModelBinderProvider的簡單應用
IValueProvider在MVC框架中生成的位置以及過程
IValueProvider的應用場景
IValueProvider的實現之NameValueCollectionValueProvider
生成的位置
大家可否記得在ASP.NET MVC Model綁定(二)中對于Model綁定器生成位置的描述,這里借用一下那副描述生成位置的示意圖,
圖1

圖1中所示,藍色線條執行流程中,在Model綁定器生成后,即會生成IValueProvider類型,說是生成有點不妥,改成獲取吧。為什么這樣說在下面的生成部分會講到
生成的過程
我們先看一下圖1中藍色線條流程的實現代碼。
代碼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);
}對于代碼1-1中所示的方法,不用去管的它的返回類型以及這個方法的作用,我們現在想知道的就是IValueProvider是怎么來的!!!
從代碼1-1中,我們可以明確的看到在生成Model綁定器過后,MVC框架從ControllerContext控制器上下文參數對象中獲得了當前請求所請求的控制器的引用,然后根據當前的控制器對象引用獲取到IValueProvider類型。
然后MVC框架會實例化ModelBindingContext類型,并且把剛剛獲取的IValueProvider類型賦值到其中的ValueProvider屬性上。
對于ModelBindingContext類型,Model綁定上下文對象,看下它的定義代碼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; }
//
// 摘要:
// 獲取或設置值提供程序。
//
// 返回結果:
// 值提供程序。
public IValueProvider ValueProvider { get; set; }
}這里我們只需初步的了解ModelBindingContext類型就行了,回到主題中,上面說到從當前控制器對象的引用中直接獲取的,那我們就去看一下控制器中的ValueProvider屬性。我們就來看一下Controller類型,代碼1-3.
代碼1-3
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
{
……
}跟大家開了個玩笑,緩解下氣氛。Controller類型中并沒有我們所要找的屬性,有的朋友想到了,對的是在基類類型中的,確實是在ControllerBase類型中的(代碼1-4)。
代碼1-4
public abstract class ControllerBase : IController
{
……
public IValueProvider ValueProvider { get; set; }
}難道我們在使用IValueProvider的時候是要賦值到控制器對象上的嗎?
當然不是了,我們看一下代碼1-4中ValueProvider屬性的實現,示例代碼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;
}
}看到這里想必大家就應該已經了解了IValueProvider類型的由來了,是從系統的ValueProviderFactories類型的Factories屬性中來根據當前控制器上下文獲取到的。
這里我們看一下生成IValueProvider類型的幾個相關類型的定義,示例代碼1-6。
代碼1-6
public static class ValueProviderFactories
{
// 摘要:
// 獲取應用程序的值提供程序工廠的集合。
//
// 返回結果:
// 值提供程序工廠對象的集合。
public static ValueProviderFactoryCollection Factories { get; }
}
public class ValueProviderFactoryCollection : Collection<ValueProviderFactory>
{
public ValueProviderFactoryCollection();
public ValueProviderFactoryCollection(IList<ValueProviderFactory> list);
// 摘要:
// 為指定控制器上下文返回值提供程序工廠。
//
// 參數:
// controllerContext:
// 一個對象,該對象封裝有關當前 HTTP 請求的信息。
//
// 返回結果:
// 用于指定控制器上下文的值提供程序工廠對象。
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();
// 摘要:
// 為指定控制器上下文返回值提供程序對象。
//
// 參數:
// controllerContext:
// 一個對象,該對象封裝有關當前 HTTP 請求的信息。
//
// 返回結果:
// 值提供程序對象。
public abstract IValueProvider GetValueProvider(ControllerContext controllerContext);
}ValueProviderFactories類型的這種模式前面見過太多了,就不說了,它里面包含著ValueProviderFactoryCollection類型的靜態屬性,而ValueProviderFactoryCollection類型又是ValueProviderFactory類型的集合類型,所以在最終生成IValueProvider類型的時候也是先遍歷ValueProviderFactoryCollection類型,獲取每個ValueProviderFactory類型的實例并且來生成IValueProvider類型,這里也是最先匹配而不是最優匹配。
這里捎帶一句,可以用控制器上下文對象來對ValueProviderFactory類型中的生成邏輯進行分類,針對不同的控制器生成不同的IValueProvider類型。對于IValueProvider類型的使用后面篇幅會有說明。
創新互聯www.cdcxhl.cn,專業提供香港、美國云服務器,動態BGP最優骨干路由自動選擇,持續穩定高效的網絡助力業務部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統配攻擊溯源,準確進行流量調度,確保服務器高可用性。佳節活動現已開啟,新人活動云服務器買多久送多久。
當前標題:ASP.NETMVCModel綁定(四)-創新互聯
文章位置:http://www.js-pz168.com/article6/dpegig.html
成都網站建設公司_創新互聯,為您提供域名注冊、云服務器、網站策劃、網站制作、網站設計公司、App設計
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯