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框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并 ...
随机推荐
- ViewPager学习及使用(一)
一:基础篇 1.ViewPager的简介和作用ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view1)ViewPager类直接继承了ViewGroup类,所有它 ...
- Memcached基础介绍
1.memcached是什么,有什么作用? )memcached是一个开源的.高性能的内存的缓存软件,从名称上看mem就是内存的意思,而cache就是缓存的意思. )memcached通过在事先规划好 ...
- 面向对象封装 classmethod和staticmethod方法
接口类 接口类:是规范子类的一个模板,只要接口类中定义的,就应该在子类中实现接口类不能被实例化,它只能被继承支持多继承接口隔离原则:使用多个专门的接口,而不使用单一的总接口.即客户端不应该依赖那些不需 ...
- 《TCP/IP详解:卷一》-TCP部分讲解
TCP/IP协议 作者:Danbo 2015-7-2 本文为参考TCP/IP详解卷一,某些知识点加上了作者自己的理解,如有错误,欢迎指正,可以微博联系我! TCP包格式和IP包格式如下: TCP的正常 ...
- JS相关方法总计
1. 锚点的使用: 简单使用: <a href="#001">跳到001</a> ...文字省略 <a name="001" id ...
- 20145201 《Java程序设计》第四周学习总结
20145201 <Java程序设计>第四周学习总结 教材学习内容总结 本周学习了课本第六.七章内容,即继承与多态.接口与多态. 第六章 继承与多态 6.1 何谓继承 6.1.1 继承共同 ...
- 编译lineageos
lineageos 2 -- 编译rom包 fu*k小米,手机老是1年左右出现充不进去电.前段时间我的红米note4x突然充不进去电了,只好新买了个手机(买手机先看lineageos支持列表 ^_^) ...
- [Ctsc2000]冰原探险
Description 传说中,南极有一片广阔的冰原,在冰原下藏有史前文明的遗址.整个冰原被横竖划分成了很多个大小相等的方格.在这个冰原上有N个大小不等的矩形冰山,这些巨大的冰山有着和南极一样古老的历 ...
- Floyd算法--一个人的旅行
2017-07-27 22:37:32 writer:pprp 题目如下: 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人 ...
- Sudoku Solver, 求数独
问题描述:填充数独表中空元素.空元素为'.' 算法分析:没填充一个数,都要看这个数所在的行,列,小矩阵是否合法.然后还要看整个数独表是否正确,而判断整个数独表只能通过递归,因为前一个结果的判断要依赖后 ...
