码迷,mamicode.com
首页 > Web开发 > 详细

MVC框架中的值提供(一)

时间:2015-12-17 23:59:30      阅读:465      评论:0      收藏:0      [点我收藏+]

标签:

     在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 = 0; 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, 1);
             converted[0] = element;
             return converted;
         }
      }
      else if (valueAsArray != null)
      {
         if (valueAsArray.Length > 0)
         {
            value = valueAsArray.GetValue(0);
            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框架中的值提供(一)

标签:

原文地址:http://www.cnblogs.com/h20064528/p/5054868.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!