asp.net mvc源码分析-Action篇 IModelBinder
我们首先还是看看ReflectedParameterBindingInfo的Binder属性吧:
public override IModelBinder Binder {
get {
IModelBinder binder = ModelBinders.GetBinderFromAttributes(_parameterInfo,
() => String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedParameterBindingInfo_MultipleConverterAttributes,
_parameterInfo.Name, _parameterInfo.Member));
return binder;
}
}
在ModelBinders中有一个属性public static ModelBinderDictionary Binders,这个binders内容如下
ModelBinderDictionary binders =new ModelBinderDictionary(){
{ typeof(HttpPostedFileBase), new HttpPostedFileBaseModelBinder()},
{ typeof(byte[]), new ByteArrayModelBinder()},
{ typeof(Binary), new LinqBinaryModelBinder()}
};
说明默认的情况下就提供者3个Binder,但是这个属性是共有静态的,所以我们可以往里面添加自己的binder类,和前面文章讲的Filiter以及后面要讲的ValueProvider一样,
如在 Application_Start()方法中 ModelBinders.Binders.Add(xxx,xxxx)很不是很方便扩展了。
ModelBinders的GetBinderFromAttributes这个方法一看我们就能猜到它的逻辑了,
CustomModelBinderAttribute[] attrs = (CustomModelBinderAttribute[])element.GetCustomAttributes(typeof(CustomModelBinderAttribute), true /* inherit */);
获取 当前参数的CustomModelBinderAttribute特性,如果有该特性就调用第一个特性的GetBinder()方法并返回其值,没有特性则返回null,如果有多个特性则抛出异常,说明一个参数上是不可以有多个CustomModelBinderAttribute特性的,正样 ReflectedParameterBindingInfo的binder属性就设置好了。
下面 该轮到ControllerActionInvoker的Binders属性,
protected internal ModelBinderDictionary Binders {
get {
if (_binders == null) {
_binders = ModelBinders.Binders;
}
return _binders;
}
set {
_binders = value;
}
}
可以 看到默认他返回的是ModelBinders.Binders。
接下来看看 IModelBinder binder = GetModelBinder(parameterDescriptor)这句究竟怎么返回的binder,
return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);
太简单了 ,首先看看参数是否有binder特性,如果有就返回相应的binder,否者根据参数类型获取对应的binder。
其 方法如下:
[csharp]
public IModelBinder GetBinder(Type modelType) {
return GetBinder(modelType, true /* fallbackToDefault */);
}
public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault) {
if (modelType == null) {
throw new ArgumentNullException("modelType");
}
return GetBinder(modelType, (fallbackToDefault) ? DefaultBinder : null);
}
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;
}
public IModelBinder GetBinder(Type modelType) {
return GetBinder(modelType, true /* fallbackToDefault */);
}
public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault) {
if (modelType == null) {
throw new ArgumentNullException("modelType");
}
return GetBinder(modelType, (fallbackToDefault) ? DefaultBinder : null);
}
private IModelBinder GetBinde
补充:Web开发 , ASP.Net ,