?
快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

同樂城娛樂同樂城:【ASP.NET MVC教程】6、Model Binding的實現示例

?

在Filter和Action的履行 中說到,ControllerActionInvoker工具在InvokeAction措施中調用了GetParameters措施實現了model binding,先來看下這個措施:

protected virtual IDictionarystring, object> GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {

Dictionarystring, object> parametersDict = new Dictionarystring, object>(StringComparer.OrdinalIgnoreCase);ParameterDescriptor[] parameterDescriptors = actionDescriptor.GetParameters();

foreach (ParameterDescriptor parameterDescriptor in parameterDescriptors) {

parametersDict[parameterDescriptor.ParameterName] = GetParameterValue(controllerContext, parameterDescriptor);}

return parametersDict;}

首先經由過程actionDescriptor得到action參數的信息,這里的actionDescriptor實際上是一個ReflectedActionDescriptor,得到參數的措施自然是經由過程反射,不深入闡發了。緊接著就對每個參賽調用了GetParameterValue措施:

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) {

// collect all of the necessary binding propertiesType parameterType = parameterDescriptor.ParameterType;

IModelBinder binder = GetModelBinder(parameterDescriptor);IValueProvider valueProvider = controllerContext.Controller.ValueProvider;

string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;Predicatestring> propertyFilter = GetPropertyFilter(parameterDescriptor);

// finally, call into the binder

ModelBindingContext bindingContext = new ModelBindingContext() {FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified

ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),ModelName = parameterName,

ModelState = controllerContext.Controller.ViewData.Mo同樂城娛樂同樂城delState,PropertyFilter = propertyFilter,

ValueProvider = valueProvider};

object result = binder.BindModel(controllerContext, bindingContext);return result ?? parameterDescriptor.DefaultValue;

}

這個措施中完成了幾件事,首先是得到Model Binder,其次是得到Value Provider,再得到Property Filter,終極把這些信息組成ModelBindingContext,交給binder的BindModel措施實現綁定。先看若何得到Model Binder和Value Provider,這里將是擴展model binding的動手點。GetModelBinder措施如下:

private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) {

// look on the parameter itself, then look in the global tablereturn parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);

}

假如經由過程action的參數的Atrribute闡清楚明了采納什么binder的話就優先應用這個binder,否則從全局binder中查找。這里Binders是一個ModelBinderDictionary工具,其初始化是在ModelBinders類中的CreateDefaultBinderDictionary措施:

private static ModelBinderDictionary CreateDefaultBinderDictionary() {

// We can't add a binder to the HttpPostedFileBase type as an attribute, so we'll just// prepopulate the dictionary as a convenience to users.

ModelBinderDictionary binders = new ModelBinderDictionary() {{ typeof(HttpPostedFileBase), new HttpPostedFileBaseModelBinder() },

{ typeof(byte[]), new ByteArrayModelBinder() },{ typeof(Binary), new LinqBinaryModelBinder() }

};return binders;

}

在這里籌備了幾個默認的ModelBinder.籌備事情完成之后,看真正的GetBinder措施,這個措施顛末幾個重載的措施之后,終極調用的是如下的措施:

return GetBinder(modelType, (fallbackToDefault) ? DefaultBinder : null);

這里fallbackToDefault是true,DefaultBinder便是一個DefaultModelBinder工具,這個措施的實現如下:

private IModelBinder GetBinder(Type modelType, IModelBinder fallbackBinder) {

// Try to look up a binder for this type. We use this order of precedence:// 1. Binder returned from provider

// 2. Binder registered in the global table// 3. Binder attribute defined on the type

// 4. Supplied fallback binderIModelBinder binder = _modelBinderProviders.GetBinder(modelType);

if (binder != null) {return binder;

}if (_innerDicti同樂城娛樂同樂城onary.TryGetValue(modelType, out binder)) {

return binder;}

binder = ModelBinders.GetBinderFromAttributes(modelType,() => String.Format(CultureInfo.CurrentCultu同樂城娛樂同樂城re, MvcResources.ModelBinderDictionary_MultipleAttributes, modelType.FullName));

return binder ?? fallbackBinder;}

加上注釋的贊助,很輕易理解獲取一個類型對應的model binder的歷程是若何的。首先是經由過程IModelBinderProvider來查找,這里的modelBinderProviders在默認環境下便是ModelBinderProviders.BinderProviders屬性,這是ModelBinderProviderCollection類型的工具。我們要應用自定義的model binder,一個措施便是實現一個IModelBinderProivder,并且經由過程ModelBinderProviders.BinderProviders.Add措施注冊到全局的provider表中。第二個道路是經由過程現有的binder表,這里的_innerDictionary是一個Dictionary類型的工具,也便是ModelBinderDictionary實際存儲數據的地方,ModelBinders.Binders.Add措施就會直接往這個dictionary中添加數據。第三個道路是經由過程待綁定類型的Attribute來加載binder。著末,假如上面的道路都沒有找到binder,那么就用默認的DefaultModelBinder,大年夜多半時刻這個DefaultModelBinder已經足夠強大年夜。暫時先跳過這個DefaultModelBinder的實現,再回到GetParameterValue中,當獲得相宜的model binder之后還必要得到value provider:

IValueProvider valueProvider = controllerContext.Controller.ValueProvider;

這里的ValueProvider是定義在ControllerBase類型中的:

public IValueProvider ValueProvider {

get {if (_valueProvider == null) {

_valueProvider = ValueProviderFactories.Factories.GetValueProvider(ControllerContext);}

return _valueProvider;}

set {_valueProvider = value;

}}

下面來看下 ValueProviderFactories的實現:

public static class ValueProviderFactories {

private static readonly ValueProviderFactoryCollection _factories = new ValueProviderFactoryCollection() {

new ChildActionValueProviderFactory(),new Fo同樂城娛樂同樂城rmValueProviderFactory(),

new JsonValueProviderFactory(),new RouteDataValueProviderFactory(),

new QueryStringValueProviderFactory(),new HttpFileCollectionValueProviderFactory(),

};

public static ValueProviderFactoryCollection Factories {get {

return _factories;}

} }

這個類初始化了一系列默認的ValueProviderFactory。再看下GetValueProvider(ControllerContext) 這個措施的實現:

public IValueProvider GetValueProvider(ControllerContext controllerContext) {

var valueProviders = from factory in _serviceResolver.Currentlet同樂城娛樂同樂城 valueProvider = factory.GetValueProvider(controllerContext)

where valueProvider != nullselect valueProvider;

return new ValueProviderCollection(valueProviders.ToList());

}

這里的做法是返回所有的能夠找到的value provider,再將其組合成一個ValueProviderCollection.再看下ValueProviderCollection的關鍵措施的實現:

public virtual ValueProviderResult GetValue(string key) {

return GetValue(key, skipValidation: false); }

public virtual ValueProviderResult GetValue(string key, bool skipValidation) {

return (from provider in thislet result = GetValueFromProvider(provider, key, skipValidation)

where result != nullselect result).FirstOrDefault();

}

internal static ValueProviderResult GetValueFromProvider(IValueProvider provider, string key, bool skipValidation) {// Since IUnvalidatedValueProvider is a superset of IValueProvider, it's always OK to use the

// IUnvalidatedValueProvider-supplied members if they're present. Otherwise just call the// normal IValueProvider members.

IUnvalidatedValueProvider unvalidatedProvider = provider as IUnvalidatedValueProvider;

return (unvalidatedProvider != null) ? unvalidatedProvider.GetValue(key, skipValidation) : provider.GetValue(key); }

這個措施返回的是第一個能夠找到value的ValueProvider返回的值。附上函數調用圖:

免責聲明:以上內容源自網絡,版權歸原作者所有,如有侵犯您的原創版權請告知,我們將盡快刪除相關內容。

您可能還會對下面的文章感興趣:

快三平台开户