一、配置概述
在.net framework平台中我们常见的也是最熟悉的就是.config
文件作为配置,控制台桌面程序是app.config
,web就是web.config
,里面的配置格式为xml格式。
在xml里面有系统生成的配置项,也有我们自己添加的一些配置,最常用的就是appsettings节点,用来配置数据库连接和参数。
使用的话就引用包system.configuration.configurationmanager
之后取里面的配置信息:
system.configuration.configurationmanager.appsettings["connectionstring"]
随着技术的发展这种配置方式显得冗余复杂,如果配置项太多层级关系参数表达凌乱,在.net core开始也将配置的格式默认成了json格式,包括现在很多的其它配置也是支持的,比如java中常用的yaml格式,为什么能支持这么多读取源和格式,其实质在于配置提供程序。
目前.net 中的配置是使用一个或多个配置提供程序执行的。 配置提供程序使用各种配置源从键值对读取配置数据,这些配置程序稍后我们会看到,读取的配置源可以是如下这些:
- 设置文件,appsettings.json
- 环境变量
- azure key vault
- azure 应用配置
- 命令行参数
- 已安装或已创建的自定义提供程序
- 目录文件
- 内存中的 .net 对象
- 第三方提供程序
二、配置初识
iconfiguration 接口是所有配置源的单个表示形式,给定一个或多个配置源,iconfiguration 类型提供配置数据的统一视图。
上图我们可能没有直观的感受,现在写一个例子来看看
(1). 新建控制台应用程序:创建控制台使用的是.net 6.0 框架,vs 2022。
安装 microsoft.extensions.configuration.json nuget 包,该包提供json配置文件读取。
install-package microsoft.extensions.configuration.json
(2). 添加appsettings.json 文件
{ "person": { "name": "xspringsun", "age": 18 } }
(3). 使用json提供程序读取json配置new一个configurationbuilder,添加json配置,addjsonfile
是在包中的iconfigurationbuilder扩展方法,其它配置提供程序也是用这种扩展方法实现。
static void main(string[] args) { iconfiguration configuration = new configurationbuilder() .addjsonfile("appsettings.json") .build(); console.writeline(configuration["person:name"]); console.writeline(configuration["person:age"]); console.writeline("hello, world!"); console.readline(); }
可以看到已经取到json配置文件中的值了,配置值可以包含分层数据。 分层对象使用配置键中的 : 分隔符表示。在下面的调试对象中我们可以看到实际configuration的providers 提供程序数组有一个值,就是我们的jsonconfigurationprovider,并且jsonconfigurationprovider里面已经读取了json的数据存储在data数组中。
对于如上几行代码干了什么呢:
- 将 configurationbuilder 实例化(new configurationbuilder)。
- 添加 "appsettings.json" 文件,由 json 配置提供程序识别(addjsonfile("appsettings.json"))。
- 使用 configuration 实例获取所需的配置
三、选项模式
这样已经实现json进行配置读取,但是取值的方式似乎和以前没什么太大变法,所以.net提供了选项模式,选项模式就是使用类来提供对相关设置组的强类型访问。
我们创建一个config
类用来转换json:
namespace configdemo { public class config { public person? person { get; set; } } public class person { public string? name { get; set; } public int age { get; set; } } }
绑定配置
iconfiguration configuration = new configurationbuilder() .addjsonfile("appsettings.json") .build(); config options = new config(); configurationbinder.bind(configuration, options); person person = configuration.getsection("person").get<person>(); console.writeline(options.person.name); console.writeline(options.person.age); console.writeline("-----------getsection获取-------------"); console.writeline(person.name); console.writeline(person.age);
用了两种方式获取配置,第一种使用configurationbinder.bind()
将整个配置绑定到对象config
上,另外一种是使用iconfiguration的getsection().get<t>()
并返回指定的类型。两种方式都可以使用,看实际需求和用途。
四、选项依赖注入
在控制台程序中我们引用di注入包,然后演示下如何进行配置的注入。关于di和ioc不清楚的看我上篇文章.net 温故知新:【7】ioc控制反转,di依赖注入
- 新建一个测试类testoptiondi
public class testoptiondi { private readonly ioptionssnapshot<config> _options; public testoptiondi(ioptionssnapshot<config> options) { _options = options; } public void test() { console.writeline("di测试输出:"); console.writeline($"姓名:{_options.value.person.name}"); console.writeline($"年龄:{_options.value.person.age}"); } }
在测试类中我们使用ioptionssnapshot<t>
接口作为依赖注入,还有其它不同定义的接口用来配置注入,关于选项接口:。
不同接口可以配合读取配置的不同方式起作用,ioptionssnapshot接口可以在配置文件改变后不同作用域进行刷新配置。接着我们修改main方法,引入di,并将addjsonfile
方法的参数reloadonchange设置为true,optional参数是否验证文件存在,建议开发时都设置为true,这样如果文件有问题会进行报错。
注入配置这句services.addoptions().configure<config>(e=>configuration.bind(e))
是关键,通过容器调用addoptions
方法注册,然后configure
方法里面是一个委托方法,该委托的作用就是将配置的信息绑定到config类型的参数e上。注册到容器的泛型选项接口,这样在testoptiondi类构造函数注入就能注入ioptionssnapshot了,这里有点绕。
static void main(string[] args) { iconfiguration configuration = new configurationbuilder() .addjsonfile("appsettings.json",optional:true,reloadonchange:true) .build(); //iservicecollection 服务 servicecollection services = new servicecollection(); //注入配置 services.addoptions().configure<config>(e=>configuration.bind(e)); //注入testoptiondi services.addscoped<testoptiondi>(); using (var provider = services.buildserviceprovider()) { //获取服务 var testoption = provider.getrequiredservice<testoptiondi>(); testoption.test(); } console.readline(); }
为了测试ioptionssnapshot接口在不同作用域会刷新配置,我们修改下main方法,用一个while循环在readline时修改json文件值,不同的scope里进行打印。
using (var provider = services.buildserviceprovider()) { while (true) { using (var scope = provider.createscope()) { //获取服务 var testoption = scope.serviceprovider.getrequiredservice<testoptiondi>(); testoption.test(); } console.readline(); } }
这个功能在web中使用很方便,因为框架的一次请求就是一个作用域,所以我们修改了配置,下次请求就能生效了,而不用重启服务。
五、其它配置
如最开始所说,不仅能配置json文件,由于各种提供程序,还可以配置其它的,但是根据配置的顺序会进行覆盖。我们只添加一个环境变量配置演示下:
首先添加提供程序包:install-package microsoft.extensions.configuration.environmentvariables
。
然后添加环境变量配置代码addenvironmentvariables()
:
iconfiguration configuration = new configurationbuilder() .addjsonfile("appsettings.json",optional:true,reloadonchange:true) .addenvironmentvariables() .build();
在vs中配置临时环境变量
这里有个扁平化配置,就是表示层级用冒号person:age
六、托管模式
对于web项目我们没有进行这么多操作它是怎么配置的呢,其实框架已经自动帮我们做了,其它非web项目也可以使用这种托管模式,在microsoft.extensions.hosting 包中,只需要使用简单的代码就能配置好。
ihost host = host.createdefaultbuilder(args).build(); await host.runasync();
其加载配置的优先级:
通过分析我们对整个配置如何运行的机制有了一个大体的了解,如果想详细了解托管模式的还是建议看官方文档:.net配置
以上就是.net 中配置从xml转向json方法示例详解的详细内容,更多关于.net配置xml转向json的资料请关注代码网其它相关文章!
发表评论