.NET Core 3.x之下的配置框架
一.配置框架的核心类库
首先我们使用.net core的配置框架需要安装额外的nuget扩展包,下面是列举最常用的几个扩展包以及所对应的配置功能
nuget package | description |
---|---|
microsoft.extensions.configuration | 配置框架的核心库,提供有关configuration的抽象类和实现类 |
microsoft.extensions.configuration.commandline | 能够使用命令参数进行配置 |
microsoft.extensions.configuration.environmentvariables | 能够使用环境变量进行配置 |
microsoft.extensions.configuration.json | 能够使用json文件进行配置 |
microsoft.extensions.configuration.xml | 能够使用xml文件进行配置 |
microsoft.extensions.configuration.ini | 能够使用ini文件进行配置 |
microsoft.extensions.configuration.binder | 支持强类型对象绑定配置 |
二.一个configuration的构建
下面我们在控制台使用内存存储配置信息并且完成一个configuration的构造,代码如下:
static void main(string[] args) { //定义一个configurationbuilder iconfigurationbuilder builder = new configurationbuilder(); //添加configurationsource builder.addinmemorycollection(new dictionary<string, string>() { {"name","foo"}, {"sex","male" }, {"job","student" }, }); //通过build构建出iconfiguration iconfiguration configuration = builder.build(); foreach (var item in configuration.getchildren()) { console.writeline($"{item.key}:{item.value}"); } console.readline(); }
输出结果:
job:student name:foo sex:male
那么我们可以看到一个configuration的构建的步骤:
定义configurationbuilder
为configurationbuilder添加configurationsource
通过configurationbuilder的build方法完成构建
三.通过命令行配置
首先我们在项目的调试的应用程序参数加入命令行参数:
代码修改如下:
builder.addinmemorycollection(new dictionary<string, string>() { {"name","foo"}, {"sex","male" }, {"job","student" }, }) .addcommandline(args);
输出:
age:23 job:student name:ryzen sex:male
同时我们在输出结果看到,key为name的value变化了,证明当不同配置源存在相同key时,会被后添加的配置源覆盖其value
四.通过环境变量配置
下面的环节由于出于演示效果,通过wpf程序来演示,首先创建好一个wpf项目,界面如下:
我们在项目的调试的环境变量添加几个参数:
在app.cs中构建一个静态属性iconfiguration,代码如下:
public partial class app : application { public static iconfiguration myconfigration => new configurationbuilder() .addenvironmentvariables() }
mainwindow.cs:
public partial class mainwindow : window { public mainwindow() { initializecomponent(); } private void button_click(object sender, routedeventargs e) { loadenv(); } private void loadenv() { string envstring = string.empty; this.textbox_env.text = $"env__isproduction:{app.myconfigration.getsection("env")["isproduction"]}"+"\n"; this.textbox_env.text += $"env__isdevelopment:{app.myconfigration.getsection("env")["isdevelopment"] }"+"\n"; this.textbox_env.text += $"class__team__group:{app.myconfigration.getsection("class:team")["group"]}"; } }
实现效果:
在注入环境变量时,还支持去前缀过滤筛选注入,修改app.cs:
public partial class app : application { public static iconfiguration myconfigration => new configurationbuilder() .addenvironmentvariables("env:") }
修改mainwindow.cs:
private void loadenv() { string envstring = string.empty; this.textbox_env.text = $"env__isproduction:{app.myconfigration.getsection("env")["isproduction"]}"+"\n"; this.textbox_env.text += $"env__isdevelopment:{app.myconfigration.getsection("env")["isdevelopment"] }"+"\n"; this.textbox_env.text += $"class__team__group:{app.myconfigration.getsection("class:team")["group"]}" +"\n"; //过滤前缀后 this.textbox_env.text += $"isproduction:{app.myconfigration["isproduction"]}"; }
效果如下:
我们会发现,之前的环境变量都被过滤了,只能读取被过滤前缀后的环境变量
配置环境变量时的注意点:
- 和json等文件不同,环境变量的key是以__双下划线为分层键,而不是:冒号
- 分层读取的时候是以冒号:来进行读取
五.通过文件来配置
1.创建和读取配置文件
首先我们新建一个configurations文件夹,然后再该文件夹创建三个配置文件
appsetting.json:
{ "human": { "name": "foo", "body": { "height": 190, "weight": 170 }, "sex": "male", "age": 24, "isstudent": true } }
appsetting.xml:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <dbservers> <sqlsever>12</sqlsever> <mysql>11</mysql> </dbservers> </configuration>
appsetting.ini:
[ini] inikey1=inivalue1 inikey2=inivalue2
在app.cs分别注入这三个文件:
public partial class app : application { public static iconfiguration myconfigration => new configurationbuilder() .addenvironmentvariables("env:") .addjsonfile(@"configurations\appsetting.json", false, true) .addxmlfile(@"configurations\appsetting.xml", false, true) .addinifile(@"configurations\appsetting.ini") .build(); }
修改mainwindow代码,分别读取这三个文件:
private void button_click(object sender, routedeventargs e) { loadenv(); loadjson(); loadxml(); loadini(); } private void loadjson() { var jsonstring = string.empty; foreach (var item in app.myconfigration.getsection("human").getchildren()) { if (item.key.contains("body")) { foreach (var body in item.getchildren()) { jsonstring += $"{body.key}:{body.value} \n"; } } else { jsonstring += $"{item.key}:{item.value} \n"; } } this.textbox_json.text = jsonstring; } private void loadxml() { var xmlstring = string.empty; foreach (var item in app.myconfigration.getsection("dbservers").getchildren()) { xmlstring += $"{item.key}:{item.value} \n"; } this.textbox_xml.text = xmlstring; } private void loadini() { var inistring = string.empty; foreach (var item in app.myconfigration.getsection("ini").getchildren()) { inistring += $"{item.key}:{item.value} \n"; } this.textbox_ini.text = inistring; }
效果如下:
2.支持文件变更时重新读取和设置变更监视
以json文件为例,我们在app.cs注入json文件时调用此方法
addjsonfile(@"configurations\appsetting.json", false, true)
该方法有是一个重载方法,最常用的是三个参数的重载方法,下面是三个参数的作用
path:文件路径
optional:默认为false,当找不到该文件路径会报错,true则不报错
reloadonchange:默认为false,当为true时支持配置文件变更后重新读取
首先,我们为appsetting.json文件设置属性,复制到输出目录=>如果较新则复制,生成操作=>内容
然后我们通过一个内置的静态方法监控文件变更,修改mainwindows.cs:
public mainwindow() { initializecomponent(); changetoken.onchange(() => app.myconfigration.getreloadtoken(), () => { messagebox.show("文件发生变更了"); }); }
效果如下:
六.强类型绑定配置
首先我们创建一个类用于绑定配置,代码如下:
public class myhumanconfig { public string name { get; set; } public body body { get; set; } public string sex { get; set; } public int age { get; set; } public bool isstudent { get; set; } } public class body { public int height { get; set; } public int weight { get; set; } }
在mainwindow.cs新增以下代码:
private void button_click(object sender, routedeventargs e) { loadenv(); loadjson(); loadxml(); loadini(); loadbind(); } private void loadbind() { var bindstring = string.empty; myhumanconfig config = new myhumanconfig();//声明变量 app.myconfigration.getsection("human").bind(config);//绑定变量 foreach (var configproperty in config.gettype().getproperties()) { if (configproperty.propertytype==typeof(body)) { var body = configproperty.getvalue(config) as body; foreach (var bodyproperty in body.gettype().getproperties()) { bindstring += $"{bodyproperty.name}:{bodyproperty.getvalue(body)} \n"; } } else { bindstring += $"{configproperty.name}:{configproperty.getvalue(config)} \n"; } } this.textbox_bind.text = bindstring; }
效果如下: