.net core系列之《从源码对Configuration的底层运行机制进行分析》
通过对Configuration源代码的分析从而来自定义一个配置数据源
1、用反编译工具来看看AddJsonFile()这个方法究竟干了什么,源代码如下:
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path)
{
return builder.AddJsonFile(null, path, false, false);
} public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional)
{
return builder.AddJsonFile(null, path, optional, false);
} public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange)
{
return builder.AddJsonFile(null, path, optional, reloadOnChange);
}
首先我们可以看到这3个重载方法,它们都是调用了下面这个方法:
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange)
{
if (builder == null)
{
throw new ArgumentNullException("builder");
}
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException(Microsoft.Extensions.Configuration.Json.Resources.Error_InvalidFilePath, "path");
}
return builder.AddJsonFile(delegate (JsonConfigurationSource s) {
s.FileProvider = provider;
s.Path = path;
s.Optional = optional;
s.ReloadOnChange = reloadOnChange;
s.ResolveFileProvider();
});
}
而这个方法呢,又是调用了下面这个方法:
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, Action<JsonConfigurationSource> configureSource)
{
return builder.Add<JsonConfigurationSource>(configureSource);
}
从上面的方法可以看出,类型参数为 JsonConfigurationSource 然后返回IConfigurationBuilder的扩展方法 Add<TSource>(this IConfigurationBuilder builder, Action<TSource> configureSource)
代码如下:
public static IConfigurationBuilder Add<TSource>(this IConfigurationBuilder builder, Action<TSource> configureSource) where TSource: IConfigurationSource, new()
{
TSource source = Activator.CreateInstance<TSource>();
if (configureSource != null)
{
configureSource(source);
}
return builder.Add(source);
}
能过这个方法,创建 JsonConfigurationSource 的一个实例,最后返回 IConfigurationBuilder 中的 Add(IConfigurationSource source) 方法,接下来我们来看看在这个方法里都干了什么吧
public IConfigurationBuilder Add(IConfigurationSource source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
this.Sources.Add(source);
return this;
} public IList<IConfigurationSource> Sources
{
[CompilerGenerated]
get
{
return this.<Sources>k__BackingField;
}
}
通过以上代码我知道了,AddJsonFile()这个方法,创建了一个 JsonConfigurationSource 的一个实例,并将AddJsonFile()中的参数给了这个对象,然后将这个对象存到一个集合中。
2、接下来我们来看看Build()这个方法干了什么:
public IConfigurationRoot Build()
{
List<IConfigurationProvider> list = new List<IConfigurationProvider>();
using (IEnumerator<IConfigurationSource> enumerator = this.Sources.GetEnumerator())
{
while (enumerator.MoveNext())
{
IConfigurationProvider provider = enumerator.Current.Build(this);
list.Add(provider);
}
}
return new ConfigurationRoot((IList<IConfigurationProvider>) list);
}
这个方法通过遍历你通过AddJsonFile()方法存放进去的 IConfigurationSource 的集合,然后通过调用 IConfigurationSource 的实现类的 Build方法 ,我们来看看这个方法是怎样的:
public override IConfigurationProvider Build(IConfigurationBuilder builder)
{
base.EnsureDefaults(builder);
return new JsonConfigurationProvider(this);
}
这个方法返回一个 IConfigurationProvider 对象,被赋给了 List<IConfigurationProvider> 集合,接下来我们来看看 JsonConfigurationProvider 这个类里面有什么
public override void Load(Stream stream)
{
try
{
base.Data = JsonConfigurationFileParser.Parse(stream);
}
catch (JsonReaderException exception)
{
string str = string.Empty;
if (stream.get_CanSeek())
{
stream.Seek((long) 0L, (SeekOrigin) SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(stream))
{
IEnumerable<string> fileContent = ReadLines(reader);
str = RetrieveErrorContext(exception, fileContent);
}
}
throw new FormatException(Microsoft.Extensions.Configuration.Json.Resources.FormatError_JSONParseError((int) exception.LineNumber, str), exception);
}
}
我们看到了这里面有一个Load()方法,这个方法就是用来加载文件中的数据的。
然后我们接着分析上面还没分析的 return new ConfigurationRoot((IList<IConfigurationProvider>) list); 这段代码
这段代码返回了一个 ConfigurationRoot 对象,还将我们所有的 IConfigurationProvider 给传了进行,它想干嘛呢?
没错,上面虽然有Load()方法,但是没人调用啊。 ConfigurationRoot 这个类就是干这个的。
public ConfigurationRoot(IList<IConfigurationProvider> providers)
{
if (providers == null)
{
throw new ArgumentNullException("providers");
}
this._providers = providers;
foreach (IConfigurationProvider p in providers)
{
p.Load();
ChangeToken.OnChange(delegate {
return p.GetReloadToken();
}, delegate {
this.RaiseChanged();
});
}
}
通过以上代码的分析我们知道了Configuration的底层运行机制
3、那么接下来我们来自定义一个获取自定义的文件的Configuration,能过以上代码我们可以分析出有几个重要的对象
1、JsonConfigurationSource:最后从这个对象的基类的Data属性中取值
2、JsonConfigurationProvider:这个里面的Load()方法用来加载文件数据
3、JsonConfigurationExtensions:这个是用来定义AddJsonFile()方法的
我们规定我们的文件后缀为.custom
CustomConfigurationSource类代码
public class CustomConfigurationSource : FileConfigurationSource
{
private string path = string.Empty;
public CustomConfigurationSource(string path)
{
this.path = path;
}
public override IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new CustomConfigurationProvider(this.path);
}
}
CustomConfigurationProvider类代码
public class CustomConfigurationProvider : ConfigurationProvider
{
private string path = string.Empty;
public CustomConfigurationProvider(string path)
{
this.path = path;
}
public override void Load()
{
var lines = System.IO.File.ReadAllLines(this.path);
var dict = new Dictionary<string, string>();
foreach (var item in lines)
{
var items = item.Split("=");
dict.Add(items[], items[]);
}
base.Data = dict;
}
}
CustomConfigurationExtensions类代码 :
public static class CustomConfigurationExtensions
{
public static IConfigurationBuilder AddCustomFile(this IConfigurationBuilder builder, string path)
{
return builder.Add(new CustomConfigurationSource(path));
}
}
最终调用代码:
static void Main(string[] args)
{
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddCustomFile("1.custom")
.Build();;
var info = configuration["host"];
Console.WriteLine(info);
Console.ReadKey();
}
结果如下:

.net core系列之《从源码对Configuration的底层运行机制进行分析》的更多相关文章
- .net core系列之《.net core内置IOC容器ServiceCollection》
一.IOC介绍 IOC:全名(Inversion of Control)-控制反转 IOC意味着我们将对象的创建控制权交给了外部容器,我们不管它是如何创建的,我们只需要知道,当我们想要某个实例时,我们 ...
- Asp.Net Core 内置IOC容器的理解
Asp.Net Core 内置IOC容器的理解 01.使用IOC容器的好处 对接口和实现类由原来的零散式管理,到现在的集中式管理. 对类和接口之间的关系,有多种注入模式(构造函数注入.属性注入等). ...
- net core体系-web应用程序-4net core2.0大白话带你入门-8asp.net core 内置DI容器(DependencyInjection,控制翻转)的一点小理解
asp.net core 内置DI容器的一点小理解 DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IO ...
- NET Core 3.0 AutoFac替换内置DI的新姿势
原文:NET Core 3.0 AutoFac替换内置DI的新姿势 .NET Core 3.0 和 以往版本不同,替换AutoFac服务的方式有了一定的变化,在尝试着升级项目的时候出现了一些问题. 原 ...
- 浏览器扩展系列————给MSTHML添加内置脚本对象【包括自定义事件】
原文:浏览器扩展系列----给MSTHML添加内置脚本对象[包括自定义事件] 使用场合: 在程序中使用WebBrowser或相关的控件如:axWebBrowser等.打开本地的html文件时,可以在h ...
- 简单讲解Asp.Net Core自带IOC容器ServiceCollection
一. 理解ServiceCollection之前先要熟悉几个概念:DIP.IOC.DI.Ioc容器: 二. 接下来先简单说一下几个概念问题: 1.DIP(依赖倒置原则):六大设计原则里面一种设计原 ...
- ASP.NET Core 2.1 : 十二.内置日志、使用Nlog将日志输出到文件
应用离不开日志,虽然现在使用VS有强大的调试功能,开发过程中不复杂的情况懒得输出日志了(想起print和echo的有木有),但在一些复杂的过程中以及应用日常运行中的日志还是非常有用. ASP.NET ...
- asp.net core 内置DI容器的一点小理解
DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IOC). 具体体现为Micorosoft.Extensio ...
- 学习笔记:GLSL Core Tutorial – Vertex Shader(内置变量说明)
1.每个Vertex Shader都有用户定义的输入属性,例如:位置,法线向量和纹理坐标等.Vertex Shaders也接收一致变量(uniform variables). uniform vari ...
- .net core 2.0学习记录(三):内置IOC与DI的使用
本篇的话介绍下IOC和ID的含义以及如何使用.Net Core中的DI. 一.我是这么理解IOC和DI的: IOC:没有用IOC之前是直接new实例来赋值,使用IOC之后是通过在运行的时候根据配置来实 ...
随机推荐
- 关于.NET中FileSystemWatcher的一些不被人注意的细节
.NET 中的FileSystemWatcher可以监控文件系统中的更改.新建.删除和重命名,关于它的事件及属性的讨论有许多,但细节性的具体在什么情况下触发这些事件讨论不多.根据个人测试,总结如下: ...
- java中Filter过滤器处理中文乱码的方法
注意问题:在学习用selvert的过滤器filter处理中文乱码时,在filter配置初始化时用了utf-8处理中文乱码,而在提交的jsp页面中却用了gbk.虽然两种都可以出来中文乱码,但是却造成了处 ...
- QQ空间首页背景图片淡出解析与不足完善
一件事情的发生总是有原因的,当然更多的是对技术本身的追求,一定要搞懂啦,废话不多说,大宝剑直插主题. 起因 以前做过一个xx项目,在登陆界面背景图片中,直接引用了一张大图,css类似于这样(backg ...
- WPF Lambda
lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 “成为”.运算符将表达式分为两部分,左边指定 ...
- Kibana插件sentinl实现邮件报警
为什么会突然想用到对日志的异常内容进行邮件报警,是因为在上周公司的线上业务多次出现锁表,开发在优化sql的同时,我也在想是不是可以对日志的异常内容进行检测并实现邮件预警. 在网上查询了一些资料后,决定 ...
- R语言列表list函数
列表是R语言中的对象,它包含不同类型的元素,比如 - 数字,字符串,向量和另一个列表等.一个列表还可以包含一个矩阵或一个函数作为它的元素.使用list()函数创建列表. 创建一个列表 下面是一个例子来 ...
- The servlets named [create_subscription] and [servlet.create] are both mapped to the url-pattern [/create] which is not permitted [duplicate]
原因,代码中在public前已经有了默认的配置路径: 如: @WebServlet("/ShowUser")public class ShowUser extends HttpSe ...
- Angular 应用中的登陆与身份验证
Angular 经常会被用到后台和管理工具的开发,这两类都会需要对用户进行鉴权.而鉴权的第一步,就是进行身份验证.由于 Angular 是单页应用,会在一开始,就把大部分的资源加载到浏览器中,所以就更 ...
- [转]OData的初步认识 OData v4 Client Code Generator
本文转自:http://www.cnblogs.com/1zhk/p/5356053.html What – OData是什么? OData - Open Data Protocol,是一个设计和使用 ...
- 读取excel的方法(可用于批量导入)
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read); //1. Reading from a binary ...