一、配置简述

  之前在.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 ,就能获取所有的配置。

.Net Core中的配置文件源码解析的更多相关文章

  1. Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  2. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  3. Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  4. Scala 深入浅出实战经典 第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  5. .Net Core缓存组件(Redis)源码解析

    上一篇文章已经介绍了MemoryCache,MemoryCache存储的数据类型是Object,也说了Redis支持五中数据类型的存储,但是微软的Redis缓存组件只实现了Hash类型的存储.在分析源 ...

  6. 解析jQuery中extend方法--源码解析以及递归的过程《二》

    源码解析 在解析代码之前,首先要了解extend函数要解决什么问题,以及传入不同的参数,会达到怎样的效果.extend函数内部处理传入的不同参数,返回处理后的对象. extend函数用来扩展对象,增加 ...

  7. .Net Core缓存组件(MemoryCache)源码解析

    一.介绍 由于CPU从内存中读取数据的速度比从磁盘读取快几个数量级,并且存在内存中,减小了数据库访问的压力,所以缓存几乎每个项目都会用到.一般常用的有MemoryCache.Redis.MemoryC ...

  8. Spring中AOP相关源码解析

    前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...

  9. Spark Core 1.3.1源码解析及个人总结

    本篇源码基于赵星对Spark 1.3.1解析进行整理.话说,我不认为我这下文源码的排版很好,不能适应的还是看总结吧. 虽然1.3.1有点老了,但对于standalone模式下的Master.Worke ...

随机推荐

  1. java代码导出数据到Excel、js导出数据到Excel(三)

     jsp内容忽略,仅写个出发按钮:          <button style="width: 100px" onclick="expertExcel()&quo ...

  2. Linux下查看USB设备信息

    首先需要将usbfs挂载一下,然后才能查看.$ mount -t usbfs none /proc/bus/usb$ cat  /proc/bus/usb/devices或者在文件(/etc/fsta ...

  3. 使用html+javascriptt实现的简易四则运算(初学JavaScript笔记)

    今天第一天学javascript,做了个简易的四则运算,提供参考,效果图: html代码: <!DOCTYPE html> <html > <head > < ...

  4. 浅谈抓取网页数据(奉上Demo)

    Demo源码 背景 曾经在公司做过一个比价系统,就是抓取其它网站上商品的价格并和自己公司的商品进行对应,然后展示出来,给pm提供一个定价的参考.后来,有同事的朋友在找工作的时候,猎头让其做一个抓取去哪 ...

  5. oracle 控制文件的重建

    目录 oracle 控制文件的重建 NORESETLOGS RESETLOGS oracle 控制文件的重建 不到最后时刻,如三个控制文件都已损坏,又没有控制文件的备份.还是不要重建控制文件,处理不好 ...

  6. rocketmq源码分析2-broker的消息接收

    broker消息接收,假设接收的是一个普通消息(即没有事务),此处分析也只分析master上动作逻辑,不涉及ha. 1. 如何找到消息接收处理入口 可以通过broker的监听端口10911顺藤摸瓜式的 ...

  7. day01_08.三大控制结构

    编程三要素:变量,运算,控制 控制: 有选择性的控制让你某部分代码执行,某部分不执行,或者来回反复执行某段代码 控制的三种基本机构:顺序,选择,循环 1.顺序 程序从上到下,顺序执行 <?php ...

  8. 【LeetCode】Longest Common Prefix(最长公共前缀)

    这道题是LeetCode里的第14道题. 题目描述: 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["f ...

  9. Leetcode 482.密钥格式化

    密钥格式化 给定一个密钥字符串S,只包含字母,数字以及 '-'(破折号).N 个 '-' 将字符串分成了 N+1 组.给定一个数字 K,重新格式化字符串,除了第一个分组以外,每个分组要包含 K 个字符 ...

  10. csa Round #70

    Digit Holes Time limit: 1000 msMemory limit: 256 MB   When writing digits, some of them are consider ...