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。

转载于:https://www.cnblogs.com/ghhlyy/archive/2013/03/03/2941171.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值