zoukankan      html  css  js  c++  java
  • MVC框架中的值提供机制(三)

        在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然就是一个Dictionnary。  

         NameValueCollection和Dictionnary都是一个键值对的集合,它们之间的不同之处在NameValueCollection运行元素具有相同的Key,Dictionnary却要求元素的Key具有唯一性。

    DictionnaryValueProvider

         在MVC框架默认的值提供程序中,ChildActionValueProvider,RouteDataValueProvider,HttpFileCollectionValueProvider等值提供程序都继承了DictionaryValueProvider类;

     public class DictionaryValueProvider<TValue> : IValueProvider, IEnumerableValueProvider
     {
            private PrefixContainer _prefixContainer;
            private readonly Dictionary<string, ValueProviderResult> _values = new Dictionary<string, ValueProviderResult>(StringComparer.OrdinalIgnoreCase);
    
            public DictionaryValueProvider(IDictionary<string, TValue> dictionary, CultureInfo culture)
            {
                if (dictionary == null)
                {
                    throw new ArgumentNullException("dictionary");
                }
    
                foreach (KeyValuePair<string, TValue> entry in dictionary)
                {
                    object rawValue = entry.Value;
                    string attemptedValue = Convert.ToString(rawValue, culture);
                    _values[entry.Key] = new ValueProviderResult(rawValue, attemptedValue, culture);
                }
            }
    }

       在DictionaryValueProvider的构造函数中接收一个key-value的字典类型,在函数内部逐个遍历这个字典类型,将每一项转换为ValueProviderResult类型,并以key-value的形式存储在Dictionary<string, ValueProviderResult> _values 中,在数据的查询都是在这个value字典里面进行查询;

       DictionaryValueProvider类继承了IValueProvider和IEnumerableValueProvider接口;

       IValueProvider:声明GetValue方法和ContainsPrefix方法,前者根据key获得对应的Value,这个key有可能是带前缀的;后者是判断是否有给定前缀的key。

       IEnumerableValueProvider:继承IValueProvider。针对目标类型为集合(Collection)的数据提供,生命了GetKeysFromPrefix方法,返回容器中具有指定前缀的Key,这个过程默认是需要验证的。

       

     private PrefixContainer PrefixContainer
     {
        get
         {
           if (_prefixContainer == null)
           {
               _prefixContainer = new PrefixContainer(_values.Keys);
           }
           return _prefixContainer;
          }
      }
    public virtual bool ContainsPrefix(string prefix) { return PrefixContainer.ContainsPrefix(prefix); } public virtual ValueProviderResult GetValue(string key) { if (key == null) { throw new ArgumentNullException("key"); } ValueProviderResult valueProviderResult; _values.TryGetValue(key, out valueProviderResult); return valueProviderResult; } public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix) { return PrefixContainer.GetKeysFromPrefix(prefix); }

    DictionaryValueProvider类中的ContainsPrefix方法和GetKeysFromPrefix方法实际上是调用的PrefixContainer中的对应方法,在MVC框架中默认为PrefixContainer类;而GetValue根据key查找value字典的数据;因此DictionaryValueProvider类的作用实际上是做数据加工的作用,对应数据进行筛选的数据源来源于外部,通过构造方法的参数传入;

    ChildActionValueProvider

    public sealed class ChildActionValueProvider : DictionaryValueProvider<object>
    {
       private static string _childActionValuesKey = Guid.NewGuid().ToString();
       public ChildActionValueProvider(ControllerContext controllerContext)
                : base(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)
       {
       }
    }

          ChildActionValueProvider专门服务于针对子Action方法参数的Model绑定。ChildActionValueProvider类在创建的过程中会把controllerContext.RouteData.Values坐位数据源传入到DictionaryValueProvider类中;但是在ChildActionValueProvider类中重写了DictionaryValueProvider类的GetValue方法;

     private static string _childActionValuesKey = Guid.NewGuid().ToString();
     public override ValueProviderResult GetValue(string key)
     {
        if (key == null)
        {
           throw new ArgumentNullException("key");
        }
        ValueProviderResult explicitValues = base.GetValue(ChildActionValuesKey);
        if (explicitValues != null)
        {
    DictionaryValueProvider
    <object> rawExplicitValues = explicitValues.RawValue as DictionaryValueProvider<object>; if (rawExplicitValues != null) { return rawExplicitValues.GetValue(key); } } return null; }

       当调用ChildActionValueProvider的GetValue方法获取指定Key的值时,实际上并不会直接根据指定的Key去获取对应的值,而是根据通过其静态字段_childActionValuesKey值去获取对应的DictionaryValueProvider<object>对象。然后再调用该对象的GetValue根据指定的Key去获得相应的值。

      RouteDataValueProvider

     public sealed class RouteDataValueProvider : DictionaryValueProvider<object>
     {
        public RouteDataValueProvider(ControllerContext controllerContext)
                : base(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)
            {
            }
     }

    RouteDataValueProvider类是将路由数据(controllerContext.RouteData.Values)做为数据源;

    HttpFileCollectionValueProvider

     public sealed class HttpFileCollectionValueProvider : DictionaryValueProvider<HttpPostedFileBase[]>
     {
        private static readonly Dictionary<string, HttpPostedFileBase[]> _emptyDictionary = new Dictionary<string, HttpPostedFileBase[]>();
    
        public HttpFileCollectionValueProvider(ControllerContext controllerContext)
                : base(GetHttpPostedFileDictionary(controllerContext), CultureInfo.InvariantCulture)
        {
        }
    private static Dictionary<string, HttpPostedFileBase[]> GetHttpPostedFileDictionary(ControllerContext controllerContext)
        {
          HttpFileCollectionBase files = controllerContext.HttpContext.Request.Files;
            // fast-track common case of no files
           if (files.Count == 0)
           {
              return _emptyDictionary;
           }
           List<KeyValuePair<string, HttpPostedFileBase>> mapping = new List<KeyValuePair<string, HttpPostedFileBase>>();
           string[] allKeys = files.AllKeys;
           for (int i = 0; i < files.Count; i++)
           {
               string key = allKeys[i];
               if (key != null)
               {
                  HttpPostedFileBase file = HttpPostedFileBaseModelBinder.ChooseFileOrNull(files[i]);
                  mapping.Add(new KeyValuePair<string, HttpPostedFileBase>(key, file));
                }
           }
            var grouped = mapping.GroupBy(el => el.Key, el => el.Value, StringComparer.OrdinalIgnoreCase);
            return grouped.ToDictionary(g => g.Key, g => g.ToArray(), StringComparer.OrdinalIgnoreCase);
      }

          HttpFileCollectionValueProvider类是文件上传的的值提供程序,在HTTP请求的HttpRequestBase对象中,上传文件通过只读属性Files表示;在构造函数中通过GetHttpPostedFileDictionary方法创建一个key为文件名Value为HttpPostedFileBase类型的字典类型作为数据源;

  • 相关阅读:
    17. Letter Combinations of a Phone Number
    16. 3Sum Closest
    15. 3Sum
    14. Longest Common Prefix
    13. Roman to Integer
    12. Integer to Roman
    11. Container With Most Water
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/h20064528/p/5057655.html
Copyright © 2011-2022 走看看