目录
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)
- }
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;
- }
- }
不同的数据类型, 有不同的数据结构.
所以针对他们的绑定机制也是不同的.
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 能实现哪种类型的绑定
备注
来源: http://www.cnblogs.com/neverc/p/6006274.html