开通VIP,畅享免费电子书等14项超值服
首页
好书
留言交流
下载APP
联系客服
2024.04.29北京
说到配置,绝大部分系统都会有配置,不需要配置的系统是非常少的,想想以前做.net开发时,我们常常将配置放到web.config中,然后使用ConfigurationManager去读取。
初次接触到.netcore的同学,在项目中看到有一个appsettings.json文件,确实这个appsettings.json文件是做配置用的,所以想当然的把它看做.net开发中的web.config一样,但是我们要清除,.netcore并不依赖appsettings.json文件中的配置。
一、原理
IConfigurationBuilder
IConfiguration
表示配置集合的接口,一般的,程序通过从DI获取IConfiguration接口的实例来获取配置
IConfigurationRoot
IConfigurationSection
IConfigurationSource
IConfigurationProvider
于是乎,将它们串接起来,流程就是这样的:
1、提供一个实现了IConfigurationProvider接口的配置提供类,它需要提供配置的读取以及更新等操作
2、提供一个IConfigurationSource接口实现类,它负责创建IConfigurationProvider。
3、创建一个IConfigurationBuilder配置建造者对象,然后将IConfigurationSource添加进配置构造者中,这里我们一般都采用IConfigurationBuilder的拓展方法来实现。
4、使用IConfigurationBuilder构造一个IConfigurationRoot,然后使用这个IConfigurationRoot去操作配置。
这是一般流程,而.netcore的配置是一个拓展模块,也就是说我们可以在控制台等其他项目中引用,只需要安装包:Microsoft.Extensions.Configuration
为了更好的说明,我们可以先看IConfiguration在WebHost中是怎么集成的,已.netcore3.1为例,它的Program是这样的:
publicstaticIHostBuilderCreateDefaultBuilder(string[]args){...builder.ConfigureAppConfiguration((hostingContext,config)=>{varenv=hostingContext.HostingEnvironment;config.AddJsonFile('appsettings.json',optional:true,reloadOnChange:true).AddJsonFile($'appsettings.{env.EnvironmentName}.json',optional:true,reloadOnChange:true);if(env.IsDevelopment()&&!string.IsNullOrEmpty(env.ApplicationName)){varappAssembly=Assembly.Load(newAssemblyName(env.ApplicationName));if(appAssembly!=null){config.AddUserSecrets(appAssembly,optional:true);}}config.AddEnvironmentVariables();if(args!=null){config.AddCommandLine(args);}})...}现在可以看出为什么appsettings.json是默认的配置文件了,ConfigureAppConfiguration方法就是对配置的构造过程,这里默认最多会加载5个配置源(也就是上面config.AddXXXXX()部分,后面具体介绍)。
官方在配置方法,提供了一些默认的配置源,它们都是通过IConfigurationBuilder的拓展方法来集成配置源,这也很好的给我们展示了如何添加自己的配置源。
官方默认提供的配置源有:
Json文件
NuGet安装包:Microsoft.Extensions.Configuration.Json
provider:提供json文件的一些信息及功能操作,比如所在结构目录,监听文件状态等等,默认默认值:newPhysicalFileProvider(AppContext.BaseDirectorystring.Empty)path:json文件路径optional:表示json文件是否是可选的,如果未false,那么当json文件不存在时则会抛出异常reloadOnChange:表示是否在文件内容修改后重新加载配置,如果未false,表示不重新加载stream:json文件流比如有一个json文件(注意文件位置):
{'Hello':{'Microsoft':{'Extensions':'Configuration'}}}configuration.json我们读取是这样的:
Ini文件
NuGet安装包:Microsoft.Extensions.Configuration.Ini
比如我们有一个ini文件(注意文件位置):
[SessionName1]KeyName11=value11KeyName12=value12[Section2Name]KeyName21=value21KeyName22=value22iniFile.ini我们读取是这样的:
Xml文件
NuGet安装包:Microsoft.Extensions.Configuration.Xml
比如我们有一个xml文件(注意文件位置):
注:配置的键不包含xml中的根路径
命令行参数
NuGet安装包:Microsoft.Extensions.Configuration.CommandLine
熟悉命令行的朋友知道,经常的,在执行一个命令时,可以携带一些参数,有些使用-或者--符号,有些则没有,同样的,dotnet命令在执行可以也可以携带一些运行时参数,.netcore可以将这些参数集成到IConfiguration中。
args:命令函参数switchMappings:映射转化,主要是将-开头和--开头的配置转换成执行的键名说明一下,参数必须满足一下规则:
1、必须以-、--、/作为前缀,其中--与/等价2、如果是以-为前缀的参数,则必须使用switchMappings做一层映射,否则将抛出FormatException,所以自定义的命令行参数建议采用--作为前缀3、参数名与参数值之间使用=或者空格分隔,建议使用=比如:
dotnetXXXX.dll-a=a--b=b/c=c--e1/d2结果是:
环境变量
NuGet安装包:Microsoft.Extensions.Configuration.EnvironmentVariables
例如:
注:IConfiguration中的键值会去掉环境变量名中的前缀,不如这里我的环境变量名是CommonProgramFiles,但是IConfiguration中的配置名是ProgramFiles
IConfiguration配置
这个很简单,只看个例子就可以了:
staticvoidMain(string[]args){//JsonConfigurationBuilderbuilder1=newConfigurationBuilder();builder1.AddJsonFile('configuration.json');varconfiguration1=builder1.Build();//IniConfigurationBuilderbuilder2=newConfigurationBuilder();builder2.AddIniFile('iniFile.ini');varconfiguration2=builder2.Build();//XmlConfigurationBuilderbuilder3=newConfigurationBuilder();builder3.AddXmlFile('xmlFile.xml');varconfiguration3=builder3.Build();//EnvironmentVariablesConfigurationBuilderbuilder4=newConfigurationBuilder();builder4.AddEnvironmentVariables('Common');varconfiguration4=builder4.Build();ConfigurationBuilderbuilder=newConfigurationBuilder();builder.AddConfiguration(configuration1);builder.AddConfiguration(configuration2);builder.AddConfiguration(configuration3);builder.AddConfiguration(configuration4);varconfiguration=builder.Build();varcollections=configuration.AsEnumerable();foreach(varitemincollections){Console.WriteLine('{0}={1}',item.Key,item.Value);}}ViewCode结果:
内存集合
这个也很简单,看例子就明白了了:
文件目录
NuGet安装包:Microsoft.Extensions.Configuration.KeyPerFile
需要注意的是,文件名中的双下划线(__)作为配置节点分隔符。
比如,我们有一些文件(在属性中输出类型设置成始终复制):
代码:
用户私密文件
NuGet安装包:Microsoft.Extensions.Configuration.UserSecrets
在集成时,会涉及到一个userSecretsId,其实它的本意是一个独一无二的目录名,一般设置成GUID,我们有两种方式使用它:
方式一:直接使用
builder.AddUserSecrets('userSecretsId');方式二:通过UserSecretsIdAttribute特性
首先给某个程序集添加UserSecretsIdAttribute特性,比如我这里就是启动项目设置:
[assembly:Microsoft.Extensions.Configuration.UserSecrets.UserSecretsId('userSecretsId')]然后使用启动项目的程序集去获取:
其实AddUserSecrets是基于Json文件配置的一个实现,换句话说,我们只需要在上面的隐私文件secrets.json中配置数据,就可以集成到IConfiguration中。
比如我在上面的目录下的secrets.json(C:\Users\Administrator\AppData\Roaming\Microsoft\UserSecrets\userSecretsId\secrets.json)内容如下:
{'Secret':{'Key1':{'Key2':'Value2'},'Key3':'Value3'}}secret.json我们这样访问:
Azure云
NuGet安装包:Microsoft.Extensions.Configuration.AzureKeyVault
三、IConfiguration使用
一般的,我们要获取IConfiguration或者IConfigurationRoot,都是结合DI容器来使用的,比如我们的Startup:
这里说的Key的特殊性,指的就是Key是有层级关系的,层级采用ConfigurationPath.KeyDelimiter字段标识来分隔,默认是冒号(:),不建议修改(采用反射可修改)。
2、当我们配置由改动,需要重新加载时,可以调用IConfigurationRoot的Reload方法重新加载配置
3、IConfiguration的GetSection方法可以获取某个节点信息,参数key是相对于当前节点的,其中IConfigurationSection中有三个属性:
Key:当前节点名,不包含路径Path:从根节点到当前节点的路径Value:当前节点数据4、IConfiguration的GetConnectionString方法获取的是当前节点下的ConnectionStrings节点下指定名称子节点的数据(源码):
publicstaticstringGetConnectionString(thisIConfigurationconfiguration,stringname){returnconfiguration.GetSection('ConnectionStrings')[name];}5、IConfiguration有两个重要的方法:Get和Bind。
Get方法将当前节点及其子节点的数据转换并存放到指定类型的实体对象的属性中,并返回改实体对象。
Bind方法接收一个实体对象,并将当前节点的及其字节点的数据保存到改实体对象的属性中。
举个简单的例子,比如我们在appsettings.json中有配置:
varsection=configuration.GetSection('Data');vardata1=section.Get
四、总结
这一篇就先到这里吧,.netcore的配置还是很简单的,随便看看源码就能掌握。