当前位置:编程学习 > asp >>

Asp.net MVC源码分析--获取ModelBinder的优先级

 

在asp.net mvc 框架中我们可以对System.Web.Mvc.Binders 进行扩展我们自定义的binder 类型,但是同时它还有一些其它的方法可以实现自定义的model binder.而且mvc在使用的时候还有一些策略,现分析如下:

获取ModelBinder 对象的入口方法是GetParameterValue, 其中

IModelBinder binder = GetModelBinder(parameterDescriptor);

这一句代码决定了ModelBinder 的使用策略。

 System.Web.Mvc.ControllerActionInvoker

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

           // collect all of the necessary binding properties 

           Type parameterType = parameterDescriptor.ParameterType; 

           //Hey 请过来获取binder 的入口在这里,csdn 代段没法加高亮,垃极啊~! 

           IModelBinder binder = GetModelBinder(parameterDescriptor); 

           IValueProvider valueProvider = controllerContext.Controller.ValueProvider; 

           string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; 

           Predicate<string> 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.ModelState, 

               PropertyFilter = propertyFilter, 

               ValueProvider = valueProvider 

           }; 

  

           object result = binder.BindModel(controllerContext, bindingContext); 

           return result ?? parameterDescriptor.DefaultValue; 

       } 

 

private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) { 

          // look on the parameter itself, then look in the global table 

        return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType); 

      } 

  

这里优先从parameterDescriptor.BindingInfo中得到IModelBinder, 接下来我们看一下怎么从parameterDescriptor中获取binder

首先找到ReflectedActionDescriptor对象,可以看到在GetParameters方法中生成了ReflectedParameterDescriptor 对象,

System.Web.Mvc.ReflectedActionDescriptor

public override ParameterDescriptor[] GetParameters() { 

         ParameterDescriptor[] parameters = LazilyFetchParametersCollection(); 

  

         // need to clone array so that user modifications aren't accidentally stored 

         return (ParameterDescriptor[])parameters.Clone(); 

     } 

view plain

private ParameterDescriptor[] LazilyFetchParametersCollection() { 

        return DescriptorUtil.LazilyFetchOrCreateDescriptors<ParameterInfo, ParameterDescriptor>( 

            ref _parametersCache /* cacheLocation */, 

            MethodInfo.GetParameters /* initializer */, 

            parameterInfo => new ReflectedParameterDescriptor(parameterInfo, this) /* converter */); 

    } 

  

这个对象中调用了ModelBinders.GetBinderFromAttributes方法来获取binder

ReflectedParameterDescriptor -> ReflectedParameterBindingInfo

public override IModelBinder Binder { 

           get { 

               IModelBinder binder = ModelBinders.GetBinderFromAttributes(_parameterInfo, 

                   () => String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedParameterBindingInfo_MultipleConverterAttributes, 

                       _parameterInfo.Name, _parameterInfo.Member)); 

  

               return binder; 

           } 

       } 

System.Web.Mvc.ModelBinders

internal static IModelBinder GetBinderFromAttributes(ICustomAttributeProvider element, Func<string> 

 errorMessageAccessor) {  

CustomModelBinderAttribute[] attrs = (CustomModelBinderAttribute[])element. 

GetCustomAttributes(typeof(CustomModelBinderAttribute),  

true /* inherit */);  

  

return GetBinderFromAttributesImpl(attrs, errorMessageAccessor); 

 } 

  

接下来我们看

return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);

语句后面的的分支.

System.Web.Mvc.ModelBinderDictionary 

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 binder 

  

          IModelBinder binder =

补充:Web开发 , ASP.Net ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,