ASP.NET MVC Model绑定(四)
ASP.NET MVC Model绑定(四)
前言
前面的篇幅对于Model绑定器IModelBinder以及实现类型、Model绑定器提供程序都作了粗略的讲解,可以把Model绑定器想象成一个大的容器,为什么这么说呢?留个疑问在这里。
首先控制器的方法参数可能是很多种类型的、可能是多个同一种类型的,应对这种情况MVC框架使用的绑定实现都是IValueProvider来做的,而针对参数类型的不同等等一些情况,IValueProvider的实现类型也是有很大的差异的,这些具体实现的讲解会在后续的篇幅中讲解。
都说旁观者清,我们不要走进MVC框架,站在外面看。本篇会已站在外面的角度去对IValueProvider做个描述。
Model绑定
- IModelBinder、自定义Model绑定器简单实现
- Model绑定器在MVC框架中的位置
- MVC中的默认Model绑定器生成过程
- IModelBinderProvider的简单应用
- IValueProvider在MVC框架中生成的位置以及过程
- IValueProvider的应用场景
- IValueProvider的实现之NameValueCollectionValueProvider
IValueProvider在MVC框架中生成的位置以及过程
生成的位置
大家可否记得在ASP.NET MVC Model绑定(二)中对于Model绑定器生成位置的描述,这里借用一下那副描述生成位置的示意图,
图1

图1中所示,蓝色线条执行流程中,在Model绑定器生成后,即会生成IValueProvider类型,说是生成有点不妥,改成获取吧。为什么这样说在下面的生成部分会讲到
生成的过程
我们先看一下图1中蓝色线条流程的实现代码。
代码1-1
protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
Type parameterType = parameterDescriptor.ParameterType;
IModelBinder modelBinder = this.GetModelBinder(parameterDescriptor);
IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor);
ModelBindingContext context2 = new ModelBindingContext
{
FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null,
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),
ModelName = str,
ModelState = controllerContext.Controller.ViewData.ModelState,
PropertyFilter = propertyFilter,
ValueProvider = valueProvider
};
ModelBindingContext bindingContext = context2;
return (modelBinder.BindModel(controllerContext, bindingContext) ?? parameterDescriptor.DefaultValue);
}
对于代码1-1中所示的方法,不用去管的它的返回类型以及这个方法的作用,我们现在想知道的就是IValueProvider是怎么来的!!!
从代码1-1中,我们可以明确的看到在生成Model绑定器过后,MVC框架从ControllerContext控制器上下文参数对象中获得了当前请求所请求的控制器的引用,然后根据当前的控制器对象引用获取到IValueProvider类型。
然后MVC框架会实例化ModelBindingContext类型,并且把刚刚获取的IValueProvider类型赋值到其中的ValueProvider属性上。
对于ModelBindingContext类型,Model绑定上下文对象,看下它的定义代码1-2。
代码1-2
public class ModelBindingContext
{
public ModelBindingContext();
public ModelBindingContext(ModelBindingContext bindingContext);
public bool FallbackToEmptyPrefix { get; set; }
public object Model { get; set; }
public ModelMetadata ModelMetadata { get; set; }
public string ModelName { get; set; }
public ModelStateDictionary ModelState { get; set; }
public Type ModelType { get; set; }
public Predicate<string> PropertyFilter { get; set; }
public IDictionary<string, ModelMetadata> PropertyMetadata { get; }
//
// 摘要:
// 获取或设置值提供程序。
//
// 返回结果:
// 值提供程序。
public IValueProvider ValueProvider { get; set; }
}
这里我们只需初步的了解ModelBindingContext类型就行了,回到主题中,上面说到从当前控制器对象的引用中直接获取的,那我们就去看一下控制器中的ValueProvider属性。我们就来看一下Controller类型,代码1-3.
代码1-3
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
{
……
}
跟大家开了个玩笑,缓解下气氛。Controller类型中并没有我们所要找的属性,有的朋友想到了,对的是在基类类型中的,确实是在ControllerBase类型中的(代码1-4)。
代码1-4
public abstract class ControllerBase : IController
{
……
public IValueProvider ValueProvider { get; set; }
}
难道我们在使用IValueProvider的时候是要赋值到控制器对象上的吗?
当然不是了,我们看一下代码1-4中ValueProvider属性的实现,示例代码1-5.
代码1-5
public IValueProvider ValueProvider
{
get
{
if (this._valueProvider == null)
{
this._valueProvider = ValueProviderFactories.Factories.GetValueProvider(this.ControllerContext);
}
return this._valueProvider;
}
set
{
this._valueProvider = value;
}
}
看到这里想必大家就应该已经了解了IValueProvider类型的由来了,是从系统的ValueProviderFactories类型的Factories属性中来根据当前控制器上下文获取到的。
这里我们看一下生成IValueProvider类型的几个相关类型的定义,示例代码1-6。
代码1-6
public static class ValueProviderFactories
{
// 摘要:
// 获取应用程序的值提供程序工厂的集合。
//
// 返回结果:
// 值提供程序工厂对象的集合。
public static ValueProviderFactoryCollection Factories { get; }
}
public class ValueProviderFactoryCollection : Collection<ValueProviderFactory>
{
public ValueProviderFactoryCollection();
public ValueProviderFactoryCollection(IList<ValueProviderFactory> list); // 摘要:
// 为指定控制器上下文返回值提供程序工厂。
//
// 参数:
// controllerContext:
// 一个对象,该对象封装有关当前 HTTP 请求的信息。
//
// 返回结果:
// 用于指定控制器上下文的值提供程序工厂对象。
public IValueProvider GetValueProvider(ControllerContext controllerContext);
protected override void InsertItem(int index, ValueProviderFactory item);
protected override void SetItem(int index, ValueProviderFactory item);
} public abstract class ValueProviderFactory
{ protected ValueProviderFactory(); // 摘要:
// 为指定控制器上下文返回值提供程序对象。
//
// 参数:
// controllerContext:
// 一个对象,该对象封装有关当前 HTTP 请求的信息。
//
// 返回结果:
// 值提供程序对象。
public abstract IValueProvider GetValueProvider(ControllerContext controllerContext);
}
ValueProviderFactories类型的这种模式前面见过太多了,就不说了,它里面包含着ValueProviderFactoryCollection类型的静态属性,而ValueProviderFactoryCollection类型又是ValueProviderFactory类型的集合类型,所以在最终生成IValueProvider类型的时候也是先遍历ValueProviderFactoryCollection类型,获取每个ValueProviderFactory类型的实例并且来生成IValueProvider类型,这里也是最先匹配而不是最优匹配。
这里捎带一句,可以用控制器上下文对象来对ValueProviderFactory类型中的生成逻辑进行分类,针对不同的控制器生成不同的IValueProvider类型。对于IValueProvider类型的使用后面篇幅会有说明。
作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
ASP.NET MVC Model绑定(四)的更多相关文章
- ASP.NET MVC Model验证(四)
ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...
- ModelBinder——ASP.NET MVC Model绑定的核心
ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...
- ASP.NET MVC Model绑定(六)
ASP.NET MVC Model绑定(六) 前言 前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框 ...
- ASP.NET MVC Model绑定(五)
ASP.NET MVC Model绑定(五) 前言 前面的篇幅对于IValueProvider的获取位置和所处的生成过程做了讲解,本篇将会对IValueProvider的使用做个基础的示例讲解,读完本 ...
- ASP.NET MVC Model绑定(三)
ASP.NET MVC Model绑定(三) 前言 看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Mod ...
- ASP.NET MVC Model绑定(二)
ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...
- ASP.NET MVC Model绑定(一)
ASP.NET MVC Model绑定(一) 前言 ModelMetadata系列的结束了,从本篇开始就进入Model绑定部分了,这个系列阅读过后你会对Model绑定有个比较清楚的了解, 本篇对于Mo ...
- ASP.NET MVC Model元数据(四)
ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数 ...
- ASP.NET MVC Model绑定
ASP.NET MVC Model绑定(一) 前言 ModelMetadata系列的结束了,从本篇开始就进入Model绑定部分了,这个系列阅读过后你会对Model绑定有个比较清楚的了解, 本篇对于Mo ...
随机推荐
- Mapreduce的文件和hbase共同输入
Mapreduce的文件和hbase共同输入 package duogemap; import java.io.IOException; import org.apache.hadoop.co ...
- App开发:模拟服务器数据接口 - MockApi
为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...
- docker——容器安装tomcat
写在前面: 继续docker的学习,学习了docker的基本常用命令之后,我在docker上安装jdk,tomcat两个基本的java web工具,这里对操作流程记录一下. 软件准备: 1.jdk-7 ...
- FREERTOS 手册阅读笔记
郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized ...
- Ajax 概念 分析 举例
Ajax是结合了访问数据库,数据访问,Jquery 可以做页面局部刷新或者说是页面不刷新,我可以让页面不刷新,仅仅是数据的刷新,没有频繁的刷页面,是现在比较常用的一种方式做页面那么它是怎么实现页面无刷 ...
- JavaScript String对象
本编主要介绍String 字符串对象. 目录 1. 介绍:阐述 String 对象的说明以及定义方式. 2. 实例属性:介绍 String 对象的实例属性: length. 3. 实例方法:介绍 St ...
- 【开源】.Net 分布式服务中心
分布式服务中心 开源地址: http://git.oschina.net/chejiangyi/Dyd.BaseService.ServiceCenter 当垂直应用越来越多,应用之间交互不可避免,将 ...
- 第一个移动前端开源项目-dailog
你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...
- 自己来实现一个简易的OCR
来做个简易的字符识别 ,既然是简易的 那么我们就不能用任何的第三方库 .啥谷歌的 tesseract-ocr, opencv 之类的 那些玩意是叼 至少图像处理 机器视觉这类课题对我这种高中没毕业的人 ...
- java面向对象六原则一法则
1. 单一职责原则:一类只做它该做的事. 2. 里氏替换原则:子类必须能够替换基类(父类),否则不应当设计为其子类. 3. 依赖倒换原则:设计要依赖于抽象而不是具体化. 4. 接口隔离原则:接口要小而 ...