zoukankan      html  css  js  c++  java
  • mvc源码解读(16)数据绑定组件ModelBinder之ModelBinderProviders

        在上一篇中我们讲到了应用在Action方法参数上述的ModelBinder,源码具体分析到:

     private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) {
                return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);
            }

    我们已经讲了ReflectedParameterBindingInfo的Binder属性,假如它为空的话,则根据参数类型来获取ModelBinder,GetBinder方法的具体实现是在ModelBinderDictionary类里面:

     public IModelBinder GetBinder(Type modelType) {
                return GetBinder(modelType, true /* fallbackToDefault */);
            }

    这个方法最终调用的又是GetBinder的一个重载方法,这个方法的第二个参数是一个bool类型,具体实现如下:

    public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault) {
                if (modelType == null) {
                    throw new ArgumentNullException("modelType");
                }
                //fallbackToDefault表示是否启用默认的DefaultModelBinder.
                return GetBinder(modelType, (fallbackToDefault) ? DefaultBinder : null);
            }

     我们可以发现GetBinder的第二个参数fallbackToDefault为true的时候表示启用mvc默认的DefaultModelBinder。该方法里面调用的又是GetBinder的另外一个重载方法,该方法也是在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 = _modelBinderProviders.GetBinder(modelType);            

                if (binder != null) {return binder;}

                if (_innerDictionary.TryGetValue(modelType, out binder)) {return binder; }

                binder = ModelBinders.GetBinderFromAttributes(modelType, () => String.Format(CultureInfo.CurrentCulture, MvcResources.ModelBinderDictionary_MultipleAttributes, modelType.FullName));

                return binder ?? fallbackBinder;        

    }

    上面列举了获取ModelBinder的四种优先顺序,我们先来看第一个优先选择的ModelBinder,是从provider里面获取的ModelBinder,具体实现是在类ModelBinderProviderCollection里面:

     public IModelBinder GetBinder(Type modelType) {

                if (modelType == null) {throw new ArgumentNullException("modelType");}

                var modelBinders = from providers in CombinedItems                               

                                             let modelBinder = providers.GetBinder(modelType)                               

                                             where modelBinder != null                               

                                             select modelBinder;

                return modelBinders.FirstOrDefault();        

    }

    对于类ModelBinderProviderCollection顾名思义我们理解为是ModelBinderProvider的一个集合,里面包括了当前应用的ModelBinderProvider列表,上面的红色代码中GetBinder方法实现的是接口IModelBinderProvider里面的GetBinder,该方法具体定义如下:

     public interface IModelBinderProvider {
            IModelBinder GetBinder(Type modelType);
        }

    但是mvc中并没有提供实现该接口的类,我在看源码的时候一直卡在这里想不通,知道看到了ModelBinderProviders这个类,我才知道了它的用意,这个先卖个关子,我们直接看ModelBinderProviders类里面的成员:

     public static class ModelBinderProviders {

            private readonly static ModelBinderProviderCollection _binderProviders = new ModelBinderProviderCollection {};

            public static ModelBinderProviderCollection BinderProviders {

                           get {return _binderProviders;}        

            }    

    }

    BinderProviders属性就是对ModelBinderProviderCollection的封装,而我们可以看到ModelBinderProviderCollection是继承自 Collection<IModelBinderProvider>,定义如下:

    public class ModelBinderProviderCollection : Collection<IModelBinderProvider>

    那既然mvc没有提供实现IModelBinderProvider的类,那ModelBinderProviders的属性BinderProviders表示的ModelBinderProvider列表什么时候被调用的呢?看过源码我们发现最终是被ModelBinderDictionary来使用,我们来看ModelBinderDictionary的一些成员:

    private IModelBinder _defaultBinder;
    private readonly Dictionary<Type, IModelBinder> _innerDictionary = new Dictionary<Type, IModelBinder>();
    private ModelBinderProviderCollection _modelBinderProviders;

    里面包含了ModelBinderProviderCollection类的实例,那这个实例是什么时候被初始化的呢?初始化之前我们知道这个集合里里面肯定是没有数据,因此我们在mvc应用程序的全局文件Global.asax里面的Application_Start()里面进行初始化的工作。如下所示:

       ModelBinderProviders.BinderProviders.Add(******);

    这样的话从provider就获取到了ModelBinder。

  • 相关阅读:
    62 ip与int类型的转换
    60再谈指针
    59任由制转换
    58进制转换工具
    吉哥工作
    apple
    找第一个非0元素的位置
    若干个数据之和 不考虑溢出
    汇编程序w=x*y+z-200
    4位bcd数转换为2进制数
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2941171.html
Copyright © 2011-2022 走看看