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

.Net Core中的配置文件源码解析的更多相关文章
- Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- .Net Core缓存组件(Redis)源码解析
上一篇文章已经介绍了MemoryCache,MemoryCache存储的数据类型是Object,也说了Redis支持五中数据类型的存储,但是微软的Redis缓存组件只实现了Hash类型的存储.在分析源 ...
- 解析jQuery中extend方法--源码解析以及递归的过程《二》
源码解析 在解析代码之前,首先要了解extend函数要解决什么问题,以及传入不同的参数,会达到怎样的效果.extend函数内部处理传入的不同参数,返回处理后的对象. extend函数用来扩展对象,增加 ...
- .Net Core缓存组件(MemoryCache)源码解析
一.介绍 由于CPU从内存中读取数据的速度比从磁盘读取快几个数量级,并且存在内存中,减小了数据库访问的压力,所以缓存几乎每个项目都会用到.一般常用的有MemoryCache.Redis.MemoryC ...
- Spring中AOP相关源码解析
前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...
- Spark Core 1.3.1源码解析及个人总结
本篇源码基于赵星对Spark 1.3.1解析进行整理.话说,我不认为我这下文源码的排版很好,不能适应的还是看总结吧. 虽然1.3.1有点老了,但对于standalone模式下的Master.Worke ...
随机推荐
- vue_music:封装scroll.vue组件
在项目中经常用到滚动,结合Better-scroll封装了sroll.vue组件参考链接:https://ustbhuangyi.github.io...http://www.imooc.com/ar ...
- Linux 常用命令(三)
一.less --分页查看文件:方面查阅(编辑)大文件 说明:支持方向键盘和鼠标向上向下浏览 -N 显示行号 二.head --output the first part of files 默认显示 ...
- python里字典的用法介绍
一.什么是字典 字典是python里的一种数据类型,特点是元素的无序性,和键key的唯一性.字典的创建方法是{key:values},字典里的键key只能是不可变的数据类型(整型,字符串或者是元组), ...
- 动态规划:Codeforces Round #427 (Div. 2) C Star sky
C. Star sky time limit per test2 seconds memory limit per test256 megabytes inputstandard input outp ...
- 《鸟哥的Linux私房菜》学习笔记(1)——文件与目录
在Linux中,任何设备都是文件,不仅如此,连数据通信的接口也有专门的文件负责.可以说,一切皆文件,目录也是一种文件,是路径映射.因此,文件系统是Linux的基础. 一.文件与目录管理命令 1.ls( ...
- 从Windows想Linux上传文件 Linux(CentOS) 上安装vsftpd
今天想在Linux上搭建个LAMP环境,以前用的Linux都安装了图形界面,但是这次用的阿里云服务器是纯命令模式,用起来有点不大适应. 最大的不适应就是获取apache等软件了,以前直接登录相应网站, ...
- 程序员必需知道的Mac OS使用技巧
macos sierra正式版发布了,于是我把我沉寂了一年没有用过了的macbook拿出来玩玩,顺便把一些常用技巧mark. 1.apple store下载软件无响应(经常出现的问题) 解决方法:更改 ...
- 深入新版BS4源码 探索flex和工程化sass奥秘
你可能已经听说了一个“大新闻”:Bootstrap4 合并了代号为#21389的PR,宣布放弃支持IE9,并默认使用flexbox弹性盒模型.这标志着:1)前端开发全面步入“现代浏览器”的时代进一步来 ...
- [python工具][1]sublime安装与配置
http://www.cnblogs.com/wind128/p/4409422.html 1 官网下载版本 http://www.sublimetext.com/3 选择 Windows - al ...
- 【java基础 16】抽象类和接口的区别
导读:前两天闲着没事儿,看了本书,然后写了点代码,在接口里面写了默认方法实现,因为书上说这个特性是从java8开始的,我还特地给测了一下java7. 没过几天,就有一个技术分享会,刚好也是讲java8 ...