asp.net mvc源码分析-Controller篇 ValueProvider

在上篇文章asp.net mvc源码分析-Action篇 IModelBinder中我们提到了ValueProvider,其实这个东西是Controller的属性,在写前面Controller的是曾打算把它写书来,后来有以下在后面用的时候在写它相关的东东吧,需求才能推动发展啊。先说明一下这个属性石很重要的,Action参数的值最总都是通过它来获取的。

   public IValueProvider ValueProvider {
            get {
                if (_valueProvider == null) {
                    _valueProvider = ValueProviderFactories.Factories.GetValueProvider(ControllerContext);
                }
                return _valueProvider;
            }
            set {
                _valueProvider = value;
            }
        }

想让我们看看ValueProviderFactories类是个什么东东

 public static class ValueProviderFactories {

        private static readonly ValueProviderFactoryCollection _factories = new ValueProviderFactoryCollection() {
            new ChildActionValueProviderFactory(),
            new FormValueProviderFactory(),
            new JsonValueProviderFactory(),
            new RouteDataValueProviderFactory(),
            new QueryStringValueProviderFactory(),
            new HttpFileCollectionValueProviderFactory(),

        };


        public static ValueProviderFactoryCollection Factories {
            get {
                return _factories;
            }
        }

    }

看来 默认就跟我们加了6个ProviderFactory啊,这个顺序很重要。

        public IValueProvider GetValueProvider(ControllerContext controllerContext) {
            var valueProviders = from factory in _serviceResolver.Current
                                 let valueProvider = factory.GetValueProvider(controllerContext)
                                 where valueProvider != null
                                 select valueProvider;

            return new ValueProviderCollection(valueProviders.ToList());
        }

GetValueProvider这个返回的是一个ValueProvider集合类ValueProviderCollection,所以我认为这个方法名应该加个s改为GetValueProviders。这里的_serviceResolver.Current就是我们默认的那6个ProviderFactory

其中 除JsonValueProviderFactory 有点特殊,其他的几个只要controllerContext有效都能返回valueProvider ,他们的valueProvider 类型依次对应如下:

ChildActionValueProviderFactory           ->ChildActionValueProvider
FormValueProviderFactory                      ->FormValueProvider
RouteDataValueProviderFactory             ->RouteDataValueProvider
QueryStringValueProviderFactory           ->QueryStringValueProvider
HttpFileCollectionValueProviderFactory->HttpFileCollectionValueProvider

而 JsonValueProviderFactory 除了要验证controllerContext数据是否有效还需要验证 json格式是否正确,所以它直接返回了一个类DictionaryValueProvider<object>

这里的每个ValueProvider实例类我们就不用管了,太细节了。

现在我们就可以得到一个ValueProviderCollection,它有一个很有用的方法

  public virtual ValueProviderResult GetValue(string key) {
            return GetValue(key, skipValidation: false);
        }

        public virtual ValueProviderResult GetValue(string key, bool skipValidation) {
            return (from provider in this
                    let result = GetValueFromProvider(provider, key, skipValidation)
                    where result != null
                    select result).FirstOrDefault();
        }
从先前得到的ValueProvider依次待用他们的GetValue方法,返回了一个不含ValueProviderResult为空的ValueProviderResult集合,最总返回这个集合中的第一个ValueProviderResult。

        internal static ValueProviderResult GetValueFromProvider(IValueProvider provider, string key, bool skipValidation) {
            // Since IUnvalidatedValueProvider is a superset of IValueProvider, it's always OK to use the
            // IUnvalidatedValueProvider-supplied members if they're present. Otherwise just call the
            // normal IValueProvider members.

            IUnvalidatedValueProvider unvalidatedProvider = provider as IUnvalidatedValueProvider;
            return (unvalidatedProvider != null) ? unvalidatedProvider.GetValue(key, skipValidation) : provider.GetValue(key);

        }

为什么会出现上面provider as IUnvalidatedValueProvider这样的代码了?因为前面提到的

QueryStringValueProvider、NameValueCollectionValueProvider都继承与NameValueCollectionValueProvider

 public class NameValueCollectionValueProvider : IValueProvider, IUnvalidatedValueProvider 
而ChildActionValueProvider、RouteDataValueProvider、HttpFileCollectionValueProvider却继承与DictionaryValueProvider
 public class DictionaryValueProvider<TValue> : IValueProvider

NameValueCollectionValueProvider的主要方法如下:

 而DictionaryValueProvider的主要方法:

  充这里可以看到ValueProviderResultPlaceholder是一个ValueProviderResult的包装类,使其数据实现延迟加载

  具体其他的什么细节之处我就不提了。在项目中我们往往要实现自己ValueProviderFactory,那么我们需要怎么注册它了在 Application_Start()加入ValueProviderFactories.Factories.Add(xxxx)。
我们举一个demo来说说怎么用的吧

  在Application_Start中加入ValueProviderFactories.Factories.Add(new CookieValueProviderFactory());

两次运行结果如图:

posted on   dz45693  阅读(2386)  评论(4编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2012年11月 >
28 29 30 31 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示