版权声明:此文章转载自_infocool
原文链接:http://www.infocool.net/kb/ASP/201610/205968.html
如需转载请联系听云College团队成员小尹 邮箱:yinhy#tingyun.com
目录
ModelBinder
ModelBinderProvider
不同类型的Model绑定
简单类型
复杂类型
其他类型
ModelBinder
ModelBinder是Model绑定的核心.
public interface IModelBinder { //绑定Model方法,返回绑定是否成功 bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext); } ModelBindingContext public class ModelBindingContext { //数据源 public IValueProvider ValueProvider { get; set; } //最终创建的对象 绑定过程就是创建Model public object Model { get; set; } //参数名称 public string ModelName { get; set; } //参数类型 public Type ModelType { get; } //参数元数据 public ModelMetadata ModelMetadata { get; set; } //属性元数据 public IDictionary<string, ModelMetadata> PropertyMetadata { get; } //存储绑定结果(包括错误信息,ValueProviderResult),该值引用自ApiController的ModelState public ModelStateDictionary ModelState { get; set; } public bool FallbackToEmptyPrefix { get; set; } }
当ModelBinder特性的Name(为null),FallbackToEmptyPrefix为True.
FallbackToEmptyPrefix为False时,则必须数据源有前缀才能绑定上.
Web API定义了一系列的ModelBinder,这里先介绍
public class CompositeModelBinder : IModelBinder { //IModelBinder 集合 public CompositeModelBinder(params IModelBinder[] binders) //使用内部ModelBinder进行绑定Model(默认遍历一次,如果FallbackToEmptyPrefix为True,则会有2次遍历机会) public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) } ModelBinderProvider Web API通过ModelBinderProvider创建ModelBinder public abstract class ModelBinderProvider { public abstract IModelBinder GetBinder(HttpConfiguration configuration, Type modelType); }
Web API中默认注册了一系列的ModelBinderProvider
this.SetMultiple<ModelBinderProvider>(new ModelBinderProvider[8] { (ModelBinderProvider) new TypeConverterModelBinderProvider(), (ModelBinderProvider) new TypeMatchModelBinderProvider(), (ModelBinderProvider) new KeyValuePairModelBinderProvider(), (ModelBinderProvider) new ComplexModelDtoModelBinderProvider(), (ModelBinderProvider) new ArrayModelBinderProvider(), (ModelBinderProvider) new DictionaryModelBinderProvider(), (ModelBinderProvider) new CollectionModelBinderProvider(), (ModelBinderProvider) new MutableObjectModelBinderProvider() });
对应的我们先介绍一下
//同样都是组装一批ModelBinderProvider public sealed class CompositeModelBinderProvider : ModelBinderProvider { public CompositeModelBinderProvider(IEnumerable<ModelBinderProvider> providers) public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType) } ModelBinderAttribute除了通过Name设置FallbackToEmptyPrefix,还有个更重要的属性BinderType public class ModelBinderAttribute : ParameterBindingAttribute { public string Name { get; set; } //用来指定ModelBinder 或 ModelBinderProvider public Type BinderType { get; set; } }
不同类型的Model绑定
不同的数据类型,有不同的数据结构.
所以针对他们的绑定机制也是不同的.
简单类型
TypeConverterModelBinder
public sealed class TypeConverterModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); model = valueProviderResult.ConvertTo(bindingContext.ModelType); bindingContext.Model = model; return true; } }
复杂类型
在介绍复杂类型的Bind前,先介绍一下下面2个类型.
ComplexModelDto包含复杂类型的元数据和绑定结果
public class ComplexModelDto { public ComplexModelDto(ModelMetadata modelMetadata, IEnumerable<ModelMetadata> propertyMetadata) public ModelMetadata ModelMetadata { get; private set; } public Collection<ModelMetadata> PropertyMetadata { get; private set; } //key 为属性的元数据,value 为绑定结果 public IDictionary<ModelMetadata, ComplexModelDtoResult> Results { get; private set; } } ComplexModelDtoResult public sealed class ComplexModelDtoResult { //绑定结果值 public object Model { get; private set; } //验证信息 public ModelValidationNode ValidationNode { get; private set; } }
复杂类型的绑定由 MutableObjectModelBinder 和 ComplexModelDtoModelBinder共同完成.
而上面2个类型,实际就是用来在2个ModelBinder间传递的对象
public class MutableObjectModelBinder : IModelBinder { public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { //类型筛选 if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) || !MutableObjectModelBinder.CanBindType(bindingContext.ModelType)) return false; //1. 创建空对象 bindingContext.ModelMetadata.Model = Activator.CreateInstance(bindingContext.ModelType); //2. 创建ComplexModelDto对象 ComplexModelDto complexModelDto = new ComplexModelDto(bindingContext.ModelMetadata,bindingContext.PropertyMetadata); //3. 进入绑定流程 this.ProcessDto(actionContext, bindingContext, complexModelDto); return true; } internal void ProcessDto(HttpActionContext actionContext, ModelBindingContext bindingContext, ComplexModelDto dto) { //创建子ModelBindingContext var subContext = new ModelBindingContext(bindingContext) { ModelName = bindingContext.ModelName, ModelMetadata = GetMetadata(typeof(ComplexModelDto)) }; //调用ComplexModelDtoModelBinder 对ComplexModelDto进行绑定 actionContext.Bind(subContext); //对复杂类型的属性进行绑定
foreach (var result in (IEnumerable<KeyValuePair<ModelMetadata, ComplexModelDtoResult>>) dto.Results) { ModelMetadata key = result.Key; ComplexModelDtoResult dtoResult = result.Value; if (dtoResult != null) { var property = bindingContext.ModelType.GetProperty(key.PropertyName); this.SetProperty(actionContext, bindingContext, key, dtoResult,property); } } } }
ComplexModelDtoModelBinder则将所有属性再通过调度其他的ModelBinder进行绑定.并将结果保存在ComplexModelDto的Results属性中.
其他类型
Web API还提供了其他常用的数据类型 ModelBinder
CollectionModelBinder来实现 集合 类型(指的集合是实现了IEnumerable接口的类型)
ArrayModelBinder来实现 数组 类型
DictionaryModelBinder来实现 字典 类型
通过对应的ModelBinderProvider可以知道对应的ModelBinder 能实现哪种类型的绑定
备注
文章中的代码并非完整WebAPI代码,一般是经过自己精简后的.
本篇内容使用MarkDown语法编辑
首发地址:http://neverc.infocool.net/p/6006274.html