MVC框架中的值提供机制(一)
在MVC框架中action方法中的Model数据的绑定的来源有很多个,可能是http请求中的get参数或是post提交的表单数据,会是json字符串或是路径中的相关数据;MVC框架中针对这些不同的数据来源抽象了IValueProvider接口;
public interface IValueProvider
{
bool ContainsPrefix(string prefix);
ValueProviderResult GetValue(string key);
}
IValueProvider接口中的ContainsPrefix方法返回是否包含指定的前缀,GetValue方法时根据指定的key来获取相应的值数据结果;
NameValueCollection
NameValueCollection类时key和value都是字符串的字典,与Dictionary类型不同的是,一个key是可以对应多个值;
NameValueCollection collection = new NameValueCollection();
collection.Add("a", "aa");
collection.Add("a", "bb");
collection.Add("a", "cc");
collection.Add("b", "aa");
string[] rawValue = collection.GetValues("a");
string attemptedValue = collection["a"];
Console.WriteLine(attemptedValue); // aa,bb,cc
Console.WriteLine(rawValue); // [aa,bb,cc]
GetValues方法返回自定key的value的数组,attemptedValue 为指定key的value的字符串表示(项之间用,链接); ValueProviderResult
ValueProviderResult类是存储Model数据的数据来源的值信息;msdn是这样描述的”表示将一个值(如窗体发布或查询字符串中的值)绑定到操作方法参数属性或绑定到该参数本身的结果“
| 名称 | 说明 | |
|---|---|---|
![]() |
AttemptedValue | 获取或设置要转换为字符串,以便显示的原始值。 |
![]() |
Culture | 获取或设置区域性。 |
![]() |
RawValue | 获取或设置值提供程序所提供的原始值。 |
在ValueProviderResult 类中含有一个ConvertTo(Type)方法,这个方法的目的是结果封装的值转换为指定的类型。在方法内部中将ValueProviderResult 类的RawValue转化为type类型的值数据。
在ConvertTo(Type)方法内部实际上是调用的UnwrapPossibleArrayType 方法中的object value参数为RawValue,具体的处理逻辑如下:
1.当value值为空或是当前对象value是当前类的实例(当前类可以是value 的类、父类、接口),直接返回value值;
2.当Type的类型是数组类型时,首先会根据destinationType.GetElementType来获取数组元素的类型
2.1 当value值能够转化为Array 数组时,然后根据转换Array 数组的长度和数组元素的类型通过Array.CreateInstance方法创建一个类型数组,最后逐个遍历转化数组的元素调用内部的ConvertSimpleType方法转换;
2.2当value值不能够转化为Array数组时,type为数组类型时,首先调用内部ConvertSimpleType的方法获取到转换的值,然后创建一个长度为1的数组,将转换后的值写入到数组中。
3.当Type类型不是数组类型时,并且Value的类型为数组类型时
3.1当Value的类型为数组长度大于0时,获取到数组中的第一个元素值,调用内部ConvertSimpleType的方法获取到转换的值
3.2当Value的类型为数组长度为0时,直接返回null值;
4.当以上情况都不满足时,直接调用内部ConvertSimpleType的方法获取到转换的值
private static object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType)
{
if (value == null || destinationType.IsInstanceOfType(value))
{
return value;
}
Array valueAsArray = value as Array;
if (destinationType.IsArray)
{
Type destinationElementType = destinationType.GetElementType();
if (valueAsArray != null)
{
IList converted = Array.CreateInstance(destinationElementType, valueAsArray.Length);
for (int i = ; i < valueAsArray.Length; i++)
{
converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType);
}
return converted;
}
else
{
object element = ConvertSimpleType(culture, value, destinationElementType);
IList converted = Array.CreateInstance(destinationElementType, );
converted[] = element;
return converted;
}
}
else if (valueAsArray != null)
{
if (valueAsArray.Length > )
{
value = valueAsArray.GetValue();
return ConvertSimpleType(culture, value, destinationType);
}
else
{
return null;
}
}
return ConvertSimpleType(culture, value, destinationType);
}
在UnwrapPossibleArrayType 方法中经常会调用ConvertSimpleType方法,从字面意思上理解这个方法是进行简单类型的数组转换;
1.当value值为空或是当前对象value是当前类的实例(当前类可以是value 的类、父类、接口),直接返回value值;
2.当value值转换为字符串后为空字符串时直接返回null
3.通过Nullable.GetUnderlyingType方法获取type是否是可空的值类型,如果是可空的值类型,则返回基础的值类型,当value值不是字符串类型时,value是否继承了IConvertible 接口,如果是,直接调用IConvertible 接口的ToType方法.
4.当以上情况都不满足时,就会通过 TypeDescriptor.GetConverter类获取参数Type的类型转换器,获取到转换器后调用CanConvertFrom方法来获取value的type是否支持这个类型转换器,当不支持转换后,会获取value值的type类型的类型转换器;
4.1如果不支持转换并且类型转换器不能转换到type,这时候就会throw 一个InvalidOperationException异常,不过一种情况除外,当类是枚举类型时,由于EnumConverter不能转换整数,所以我们手动转化,因此会调用Enum.ToObject方法;
4.2如果类型转换器支持转换的话,就直接调用转换器的ConvertFrom的方法,否则调用ConvertTo方法来获取转化的值
private static object ConvertSimpleType(CultureInfo culture, object value, Type destinationType)
{
if (value == null || destinationType.IsInstanceOfType(value))
{
return value;
}
string valueAsString = value as string;
if (valueAsString != null && String.IsNullOrWhiteSpace(valueAsString))
{
return null;
}
Type underlyingType = Nullable.GetUnderlyingType(destinationType);
if (underlyingType != null)
{
destinationType = underlyingType;
}
if (valueAsString == null)
{
IConvertible convertible = value as IConvertible;
if (convertible != null)
{
try
{
return convertible.ToType(destinationType, culture);
}
catch
{
}
}
}
TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
bool canConvertFrom = converter.CanConvertFrom(value.GetType());
if (!canConvertFrom)
{
converter = TypeDescriptor.GetConverter(value.GetType());
}
if (!(canConvertFrom || converter.CanConvertTo(destinationType)))
{ if (destinationType.IsEnum && value is int)
{
return Enum.ToObject(destinationType, (int)value);
} string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ValueProviderResult_NoConverterExists,
value.GetType().FullName, destinationType.FullName);
throw new InvalidOperationException(message);
} try
{
object convertedValue = (canConvertFrom)
? converter.ConvertFrom(null /* context */, culture, value)
: converter.ConvertTo(null /* context */, culture, value, destinationType);
return convertedValue;
}
catch (Exception ex)
{
string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ValueProviderResult_ConversionThrew,
value.GetType().FullName, destinationType.FullName);
throw new InvalidOperationException(message, ex);
}
}
MVC框架中的值提供机制(一)的更多相关文章
- MVC框架中的值提供机制(三)
在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然 ...
- MVC框架中的值提供机制(二)
在MVC框架中存在一些默认的值提供程序模板,这些值提供程序都是通过工厂模式类创建;在MVC框架中存在需要已Factory结尾的工厂类,在值提供程序中也存在ValueProviderFactories工 ...
- [原]命令模式在MVC框架中的应用
其实在项目开发中,我们使用了大量的设计模式,只是这些设计模式都封装在框架中了,如果你想要不仅仅局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之一就是命令模式,先来看看模式是如何 ...
- 命令模式在MVC框架中的应用
事实上在项目开发中,我们使用了大量的设计模式,不过这些设计模式都封装在框架中了,假设你想要不只局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之中的一个就是命令模式,先来看看模式 ...
- MVC 框架中的缓存
在程序中加入缓存的目的很多是为了提高程序的性能,提高数据的查找效率,在MVC框架中也引入了非常多的缓存,比如Controller的匹配查找,Controller,ControllerDescripto ...
- 找到MVC框架中前端URL与后端同步的解决方案
基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...
- asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析
下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...
- 在ASP.NET MVC 框架中调用 html文件及解析get请求中的参数值
在ASP.NET MVC 框架中调用 html文件: public ActionResult Index() { using (StreamReader sr = new StreamReader(P ...
- 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现(spring MVC框架)。
本文转自http://www.cnblogs.com/davidwang456/p/4090058.html 感谢作者 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并 ...
随机推荐
- 我的Android进阶之旅------>解决:debug-stripped.ap_' specified for property 'resourceFile' does not exist.
1.错误描述 更新Android Studio到2.0版本后,出现了编译失败的问题,我clean project然后重新编译还是出现抑郁的问题,问题具体描述如下所示: Error:A problem ...
- android 布局属性详解
Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料. 第一类:属性值为true或falseandroid:layout_centerHrizontal ...
- golang SQLite3性能测试
SQLite是个小型的数据库,很简洁,即支持文件也支持内存,比较适合小型的独立项目,在没有网络的时候做一些复杂的关系数据存储和运算. 为了考察性能做10M(1000万)条记录的测试,测试机4CPU.8 ...
- tkprof工具详解二
TKPROF是一个可执行文件,自带在Oracle Server软件中,无需额外的安装. 该工具文件可以用来解析ORACLE的SQL TRACE(10046) 以便生成更可读的内容. 实际上tkp ...
- Hbase 学习笔记2----概念
说在前面,本文部分内容来源于社区官网经过适度翻译,部分根据经验总结,部分是抄袭网络博文,(不一一列举引用,在此致歉)一并列在一起,本文的目的,希望能总结出一些有用的,应该注意到的东西,基本思路是先提出 ...
- Python 实习遇见的各种面试题
Python 语法 说说你平时 Python 都用哪些库 == 和 is 区别. == 是比较两对象的值,is 是比较在内存中的地址(id), is 相当于 id(objx) == id(objy). ...
- springmvc 自定义拦截器
<mvc:interceptors> <!-- 配置自定义的拦截器 --> <bean class="com.atguigu.springmvc.interce ...
- java实现简单邮件的发送以及常见问题
java实现简单邮件的发送以及常见问题 最近遇到个需求需要实现发送邮件的功能,以前做发送邮件功能都是有邮箱用户名密码,通过用户名密码连接对应的SMTP服务器来实现邮件的发送.但是这次用公司内部的邮箱, ...
- Xcode 解决日志打印不全问题
Xcode 出了8.0后,代码运行日志过长时会出现打印不全的问题. 这可能是Xcode优化的一项,不过这也给开发带来的不必要的麻烦.下面的宏定义可以解决这一问题. #ifdef DEBUG #defi ...
- Hadoop创始人Doug Cutting寄语2017:五种让开源项目成功的方法
原文链接:http://www.infoq.com/cn/news/2017/01/Hadoop-2017-5-open-source?utm_source=tuicool&utm_mediu ...
