zoukankan      html  css  js  c++  java
  • .Net Core中的配置文件源码解析

    一、配置简述

      之前在.Net Framework平台开发时,一般配置文件都是xml格式的Web.config,而需要配置其他格式的文件就需要自己去读取内容,加载配置了。.而Net Core支持从命令行、环境变量、文件、内存、Key-per-file中加载配置,其中文件包括xml、ini、json三种文件格式。这里需要说明一下,不论哪种格式的配置文件,加载到程序中最终会以Key/Value形式保存,源码中将所有配置读取出来并保存在  Dictionary<string, string> Data  的字典中。额外说明一下Key-per-file配置方式是以文件名称为key,文件内容为value的形式。

    二、源码解析

      点击查看源码,我画了一个主要类之间的逻辑关系图,如下:

    实线表示继承关系,每条虚线表示意义已经在上面表明。可以分为4个部分,最终要构建的就是IConfigurationRoot,因为所有的配置都存储在它里面的Providers集合中的Data的字典中。

    构建它两条路径,一条通过IConfigurationSource构建IConfigurationProvider,然后通过IConfigurationProvider集合构建IConfigurationRoot,也就是图上标记的1/2两步。

    另一条是通过IConfigurationSource集合构建IConfigurationBuilder,在通过Builder方法遍历循环创建创建IConfigurationProvider集合,在通过IConfigurationProvider集合构建IConfigurationRoot。也就是图上的3/4两步。这里只讲文件配置方式,包括xml、ini、json文件。

    IConfigurationSource:

      它是配置文件的根本,它表示配置文件本身,比如继承自它的 FileConfigurationSource 里面有个Path属性,表示文件路径,会通过这个Path读取这个文件内容。如我们常用的xml、json、ini文件配置都继承自  FileConfigurationSource 。 

    IConfigurationProvider:

      前面说了,配置最终会转换为key/value的形式,而 IConfigurationProvider 就是这个装换。比如继承他的 FileConfigurationProvider ,它的构造函数需要传第一个  FileConfigurationSource   ,  FileConfigurationProvider   会根据  FileConfigurationSource   的 path 属性找到对应文件,然后读取配置文件到它的  IDictionary<string, string> Data  中。xml的读取在  XmlConfigurationProvider  中,json文件的读取在  JsonConfigurationProvider  。

            private void Load(bool reload)
            {
                //删除一些判断逻辑
                if (reload)
                {
                    Data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                }
                using (var stream = file.CreateReadStream())
                {
              //这一步会将文件里面的配置 放到Data中 不同的文件格式Load方法都有对应的实现,这里就不细看了。
                     Load(stream);
                }
               
                OnReload();
            } 

      一个 IConfigurationProvider 的实现类中会包含一个对应的  IConfigurationSource  的实现类,比如  JsonConfigurationProvider  类中包含一个 JsonConfigurationProvider  

    IConfigurationRoot:

      所有的类最终构建的目标就是IConfigurationRoot,它包含一个 IList<IConfigurationProvider> _providers 集合,而每一个  IConfigurationProvider  包含一个  IDictionary<string, string> Data  ,所以现在你现在是不是有提花灌顶的感觉。这样做的目的是一个程序可能有多个配置文件,可能有一个xml文件、一个json文件、一个Ini文件。每个配置文件会被读取到对应的  ConfigurationSource  中,然后通过它构建对应的  ConfigurationProvider  ,然后用三个  ConfigurationProvider  构建  ConfigurationRoot  。

    那这样会有一个问题,比如xml文件配置了 A的值为1,json文件也配置名称为A的值为2,那会获取谁的值呢? 下面源码可以看到,IConfigurationRoot会反转添加的顺序,循环遍历,如果找到就返回,所以后面添加的会覆盖前面添加的。

            public string this[string key]
            {
                get
                {  //_providers也就是IConfigurationRoot里面的IList<IConfigurationProvider>
                    foreach (var provider in _providers.Reverse())
                    {
                        string value;
    
                        if (provider.TryGet(key, out value))
                        {
                            return value;
                        }
                    }
                    return null;
                }
                set
                {
                    if (!_providers.Any())
                    {
                        throw new InvalidOperationException(Resources.Error_NoSources);
                    }
                    foreach (var provider in _providers)
                    {
                        provider.Set(key, value);
                    }
                }
            }

     对于Json、xml、ini文件,比如

    {
      "user": {
        "address": {
          "Provice": "浙江省",
          "city": "杭州市"
        },
        "name": "张三"
      }
    }

    在Data中存储的key为 user:address:Province、user:address:city和user:name。中间以“:”分割,这个“:”是固定只读的,不可以改变的。

    三、简单使用

      创建一个WebApi项目,修改Program代码如下:

            public static void Main(string[] args)
            {
                var configRoot = new ConfigurationBuilder()
                                   .SetBasePath(Directory.GetCurrentDirectory())//设置基础路径
                                   .AddJsonFile("a.json")//加载配置
                                   .AddXmlFile("b.xml")
                                   .Build();
    
                var builder = new WebHostBuilder()
                                .UseConfiguration(configRoot)
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseKestrel()
                                .UseStartup<Startup>()
                                .Build();
                builder.Run();
            }

      然后当用的时候,只需要注入 IConfiguration ,就能获取所有的配置。

  • 相关阅读:
    托付和事件的使用
    在使用supervisord 管理tomcat时遇到的小问题
    无法安装vmware tools的解决方PLEASE WAIT! VMware Tools is currently being installed on your system. Dependin
    (转)Openlayers 2.X加载高德地图
    (转)openlayers实现在线编辑
    (转) Arcgis for js加载百度地图
    (转)Arcgis for js加载天地图
    (转) 基于Arcgis for Js的web GIS数据在线采集简介
    (转) Arcgis for js之WKT和GEOMETRY的相互转换
    (转)Arcgis for Js之Graphiclayer扩展详解
  • 原文地址:https://www.cnblogs.com/MicroHeart/p/10928888.html
Copyright © 2011-2022 走看看