打屁股 调教 .net core的成立先容(一):IConfiguration
说到成立,绝大部分系统王人会有成立,不需要成立的系统口角常少的,思思当年作念.net 斥地时打屁股 调教,咱们时常将成立放到web.config中,然后使用ConfigurationManager去读取。
首次搏斗到.net core 的同学,在技俩中看到有一个appsettings.json文献,确乎这个appsettings.json文献是作念成立用的,是以思虽然的把它看作念.net 斥地中的web.config一样,然则咱们要排除,.net core并不依赖appsettings.json文献中的成立。
.net core 提供了一种特殊天简直成立形状,大部分技能,咱们只需要温雅DI容器中的IConfiguration接话柄例对象就不错了,底下具体先容。
这里先容的.net core版块是3.1,源码地址:https://github.com/dotnet/extensions/tree/v3.1.12/src/Configuration
一、旨趣
要先容旨趣,先看与成立关连的几个接口及它们的驱散类:
IConfigurationBuilder
成立成立者接口,咱们使用它去创建成立对象,有一个驱散类:ConfigurationBuilder
IConfiguration
暗示成立围聚的接口,一般的,设施通过从DI得回IConfiguration接口的实例来得回成立
IConfigurationRoot
IConfiguration的子接口,暗示成立的根节点,换句话说,IConfigurationBuilder创建的第一个成立对象即是IConfigurationRoot接口对象,它的驱散类是:ConfigurationRoot
IConfigurationSection
IConfiguration的子接口,暗示成立的一个节点,包含节点名、节点旅途、值等等,成立节点分隔默许是冒号(:),它的驱散类是:ConfigurationSection
IConfigurationSource
成立来源接口,IConfigurationSource接口的驱散类王人很浅易,主要用于连合Options创建成立提供者IConfigurationProvider,一般的,它的作用不错合计即是接纳参数,然后在创建IConfigurationProvider时将参数传进去。
然则在读取来自文献的成立时,保举秉承轮廓类:FileConfigurationSource ,其它的就径直驱散 IConfigurationSource 就不错了,然后添加到 IConfigurationBuilder 的成立源中去。
IConfigurationProvider
成立信息的具体提供者,这个即是提供成立的得回、更新等等操作的接口,有两个垂危的轮廓类:ConfigurationProvider 和 FileConfigurationProvider
一般的,如果咱们需要集成我方的成立,需要驱散这个 IConfigurationSource 接口和 IConfigurationProvider 接口,如果咱们的成立和文献磋议,淡薄通过秉承 FileConfigurationSource 两个 FileConfigurationProvider 两个轮廓类来驱散 IConfigurationSource 和 IConfigurationProvider接口,因为这两个轮廓类仍是提供了一些咱们可能需要的功能,比如,它们不错监听文献现象,如果文献推行被修改,则不错再行加载成立。如果成立不来自文献,成立来源不错径直驱散 IConfigurationSource 接口,而通过秉承 ConfigurationProvider 来驱散 IConfigurationProvider 接口。
于是乎,将它们串接起来,经过即是这么的:
1、提供一个驱散了 IConfigurationProvider 接口的成立提供类,它需要提供成立的读取以及更新等操作
2、提供一个 IConfigurationSource 接口驱散类,它崇拜创建 IConfigurationProvider 。
3、创建一个 IConfigurationBuilder 成立成立者对象,然后将 IConfigurationSource 添加进成立构造者中,这里咱们一般王人秉承 IConfigurationBuilder 的拓展措施来驱散。
4、使用 IConfigurationBuilder 构造一个 IConfigurationRoot ,然后使用这个 IConfigurationRoot 去操作成立。
这是一般经过,而.net core的成立是一个拓展模块,也即是说咱们不错在驱散台等其他技俩中援用,只需要装配包:Microsoft.Extensions.Configuration
为了更好的讲解,咱们不错先看IConfiguration在WebHost中是怎么集成的,已.net core 3.1为例,它的Program是这么的:
向日葵视频在线观看图片
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
图片
望望Host.CreateDefaultBuilder()措施(源码),源码是这么的:
图片
public static IHostBuilder CreateDefaultBuilder(string[] args) { ... builder.ConfigureAppConfiguration((hostingContext, config) => { var env = 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)) { var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); if (appAssembly != null) { config.AddUserSecrets(appAssembly, optional: true); } } config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) ... }
图片
面前不错看出为什么appsettings.json是默许的成立文献了,ConfigureAppConfiguration措施即是对成立的构造过程,这里默许最多会加载5个成立源(也即是上头config.AddXXXXX()部分,后头具体先容)。
而ConfigureAppConfiguration的驱散即是将传进去的寄予保存(源码):
public IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate) { _configureAppConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); return this; }
这里保存是将寄予放到一个List中,也即是说ConfigureAppConfiguration措施不错屡次调用,咱们不错添加咱们我方的成立了,在Build时就会按规矩来调用(源码):
public IHost Build() { ... BuildAppConfiguration(); ... }
而BuildAppConfiguration方律例是最终构造成立的过程(源码):
图片
private void BuildAppConfiguration() { var configBuilder = new ConfigurationBuilder() .SetBasePath(_hostingEnvironment.ContentRootPath) .AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true); foreach (var buildAction in _configureAppConfigActions) { buildAction(_hostBuilderContext, configBuilder); } _appConfiguration = configBuilder.Build(); _hostBuilderContext.Configuration = _appConfiguration; }
图片
不错看到.net core里面亦然径直实例化一个ConfigurationBuilder来构造成立的,而它的Build方律例复返的是一个 IConfigurationRoot 接口对象(源码),剩下的即是使用 IConfigurationRoot 接口对象来读取更新成立了。
图片
public IConfigurationRoot Build() { var providers = new List<IConfigurationProvider>(); foreach (var source in Sources) { var provider = source.Build(this); providers.Add(provider); } return new ConfigurationRoot(providers); }
图片
二、内置的成立形状
官方在成立措施,提供了一些默许的成立源,它们王人是通过IConfigurationBuilder的拓展措施来集成成立源,这也很好的给咱们展示了怎么添加我方的成立源。
官方默许提供的成立源有:
Json文献
NuGet装配包:Microsoft.Extensions.Configuration.Json
通过 IConfigurationBuilder的AddJsonFile和AddJsonStream两个拓展措施来集成(源码),有多个重载,各参数的含义如下:
provider:提供json文献的一些信息及功能操作,比如地方结构目次,监听文献现象等等,默许默许值:new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty) path:json文献旅途 optional:暗示json文献是否是可选的,如果未false,那么当json文献不存在时则会抛出特殊 reloadOnChange:暗示是否在文献推行修改后再行加载成立,如果未false,暗示不再行加载 stream:json文献流
比如有一个json文献(珍惜文献位置):
图片
图片
{ 'Hello': { 'Microsoft': { 'Extensions': 'Configuration' } } }configuration.json
咱们读取是这么的:
图片
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile('configuration.json'); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
Ini文献
NuGet装配包:Microsoft.Extensions.Configuration.Ini
通过 IConfigurationBuilder的AddIniFile和AddIniStream两个拓展措施来集成(源码),有多个重载,各参数的含义同上Json文献。
比如咱们有一个ini文献(珍惜文献位置):打屁股 调教
图片
图片
[SessionName1] KeyName11=value11 KeyName12=value12 [Section2Name] KeyName21=value21 KeyName22=value22iniFile.ini
咱们读取是这么的:
图片
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddIniFile('iniFile.ini'); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
Xml文献
NuGet装配包:Microsoft.Extensions.Configuration.Xml
通过 IConfigurationBuilder的AddXmlFile和AddXmlStream两个拓展措施来集成(源码),有多个重载,各参数的含义同上Json文献(这亦然在告诉咱们,如果咱们要从其他文献添加,只需要访佛这些参数就不错了)。
比如咱们有一个xml文献(珍惜文献位置):
图片
图片
<?xml version='1.0' encoding='utf-8' ?> <node1> <node2>value2</node2> <node3> <node4>value4</node4> <node5>value5</node5> </node3> </node1>xmlFile.xml
咱们读取是这么的:
图片
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddXmlFile('xmlFile.xml'); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
注:成立的键不包含xml中的根旅途
号令行参数
NuGet装配包:Microsoft.Extensions.Configuration.CommandLine
闇练号令行的一又友知谈,平淡的,在实施一个号令时,不错佩戴一些参数,有些使用 - 大概 -- 符号,有些则莫得,相通的,dotnet号令在实施不错也不错佩戴一些启动时参数,.net core不错将这些参数集成到IConfiguration中。
通过 IConfigurationBuilder的AddCommandLine拓展措施来集成(源码),相通有几个重载,讲解如下:
args:号令函参数 switchMappings:映射转机,主淌若将-开端和--开端的成立调度成实施的键名
讲解一下,参数必须温顺一下礼貌:
1、必须以 -、--、/ 当作前缀,其中 -- 与 / 等价 2、如果是以 - 为前缀的参数,则必须使用 switchMappings 作念一层映射,不然将抛出 FormatException ,是以自界说的号令行参数淡薄秉承 -- 当作前缀 3、参数名与参数值之间使用 = 大概空格分隔,淡薄使用 =
比如:
图片
static void Main(string[] args) { //dotnet XXXX.dll -a=a --b=b /c=c --e 1 /d 2 var mapper = new Dictionary<string, string>() { { '-a', 'mapper-a' }, { '--b', 'mapper-b' }, { '--c', 'mapper-c' } }; ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddCommandLine(args, mapper); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
如果实施号令行:
dotnet XXXX.dll -a=a --b=b /c=c --e 1 /d 2
效果是:
图片
环境变量
NuGet装配包:Microsoft.Extensions.Configuration.EnvironmentVariables
.net core允许咱们将腹地的环境变量集成到IConfiguration成立中,通过IConfigurationBuilder的AddEnvironmentVariables拓展措施来集成(源码),同期不错指定一个前缀(拓展措施中的prefix参数),暗示要加载在成立中的哪些环境变量的前缀,而不是一谈环境变量。
举例:
图片
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddEnvironmentVariables('Common'); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
注:IConfiguration中的键值会去掉环境变量名中的前缀,不如这里我的环境变量名是CommonProgramFiles,然则IConfiguration中的成扬名是ProgramFiles
IConfiguration成立
有技能,咱们仍是存在一个IConfiguration成立了,然后咱们不错将它集成到另一个IConfiguration中去使用,通过IConfigurationBuilder的AddConfiguration拓展措施来集成(源码)。
这个很浅易,只看个例子就不错了:
图片
图片
static void Main(string[] args) { //Json ConfigurationBuilder builder1 = new ConfigurationBuilder(); builder1.AddJsonFile('configuration.json'); var configuration1 = builder1.Build(); //Ini ConfigurationBuilder builder2 = new ConfigurationBuilder(); builder2.AddIniFile('iniFile.ini'); var configuration2 = builder2.Build(); //Xml ConfigurationBuilder builder3 = new ConfigurationBuilder(); builder3.AddXmlFile('xmlFile.xml'); var configuration3 = builder3.Build(); //EnvironmentVariables ConfigurationBuilder builder4 = new ConfigurationBuilder(); builder4.AddEnvironmentVariables('Common'); var configuration4 = builder4.Build(); ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddConfiguration(configuration1); builder.AddConfiguration(configuration2); builder.AddConfiguration(configuration3); builder.AddConfiguration(configuration4); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }View Code
效果:
图片
内存围聚
有技能,咱们成立源源自某个围聚变量,这是咱们相通不错将它集成到IConfiguration中去,通过IConfigurationBuilder的AddInMemoryCollection拓展措施来集成(源码)。
这个也很浅易,看例子就昭彰明晰:
图片
static void Main(string[] args) { Dictionary<string, string> dict = new Dictionary<string, string>(); dict['Key1'] = 'Value1'; dict['Key2'] = 'Value2'; dict['Key3'] = 'Value3'; dict['Key4'] = 'Value4'; ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddInMemoryCollection(dict); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
文献目次
NuGet装配包:Microsoft.Extensions.Configuration.KeyPerFile
可能沟通到在某些情况下,有些软件将产生的数据保存着疏淡的文献中,秉承文献名当作分裂,因此作家提供了一个将这些数据文献推行当作成立的措施,秉承文献名当作key,文献推行当作value。它秉承AddKeyPerFile拓展措施集成(源码)
需要珍惜的是,文献名中的双下划线(__)当作成立节点分隔符。
比如,咱们有一些文献(在属性中输出类型树立成耐久复制):
图片
代码:
图片
static void Main(string[] args) { string directory = Path.Combine(Directory.GetCurrentDirectory(), 'files'); ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddKeyPerFile(directory, true); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } }
图片
效果:
图片
用户玄妙文献
NuGet装配包:Microsoft.Extensions.Configuration.UserSecrets
通过IConfigurationBuilder的AddUserSecrets拓展措施来集成(源码),它主要用来成立一些玄妙信息文献,这个很少使用,了解一下就行了。
在集成时,会波及到一个userSecretsId,其实它的本意是一个唯一无二的目次名,一般树立成GUID,咱们有两种形状使用它:
形状一:径直使用
builder.AddUserSecrets('userSecretsId');
形状二:通过 UserSecretsIdAttribute 特质
率先给某个设施集添加 UserSecretsIdAttribute 特质,比如我这里即是启动技俩树立:
[assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsId('userSecretsId')]
然后使用启动技俩标设施集去得回:
builder.AddUserSecrets(typeof(Program).Assembly);
上头说到userSecretsId是目次名,那是哪个目次名呢?说明源码,玄妙文献旅途使用 PathHelper.GetSecretsPathFromSecretsId()措施来得回(源码):
图片
public static string GetSecretsPathFromSecretsId(string userSecretsId) { ... const string userSecretsFallbackDir = 'DOTNET_USER_SECRETS_FALLBACK_DIR'; // For backwards compat, this checks env vars first before using Env.GetFolderPath var appData = Environment.GetEnvironmentVariable('APPDATA'); var root = appData // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ ?? Environment.GetEnvironmentVariable('HOME') // On Mac/Linux it goes to ~/.microsoft/usersecrets/ ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? Environment.GetEnvironmentVariable(userSecretsFallbackDir); // this fallback is an escape hatch if everything else fails if (string.IsNullOrEmpty(root)) { throw new InvalidOperationException('Could not determine an appropriate location for storing user secrets. Set the ' userSecretsFallbackDir ' environment variable to a folder where user secrets should be stored.'); } return !string.IsNullOrEmpty(appData) ? Path.Combine(root, 'Microsoft', 'UserSecrets', userSecretsId, SecretsFileName) : Path.Combine(root, '.microsoft', 'usersecrets', userSecretsId, SecretsFileName); }
图片
在斥地过程中,这个玄妙文献一般是:C:\Users\[USER]\AppData\Roaming\Microsoft\UserSecrets\[userSecretsId]\secrets.json
其实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
咱们这么拜访:
图片
[assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsId('userSecretsId')] namespace ConsoleApp { class Program { static void Main(string[] args) { var secretPath = Microsoft.Extensions.Configuration.UserSecrets.PathHelper.GetSecretsPathFromSecretsId('userSecretsId'); Console.WriteLine('secretPath目次在:' secretPath); ConfigurationBuilder builder = new ConfigurationBuilder(); //builder.AddUserSecrets('userSecretsId'); builder.AddUserSecrets(typeof(Program).Assembly); var configuration = builder.Build(); var collections = configuration.AsEnumerable(); foreach (var item in collections) { Console.WriteLine('{0}={1}', item.Key, item.Value); } } } }
图片
效果:
图片
Azure云
NuGet装配包:Microsoft.Extensions.Configuration.AzureKeyVault
这个和Azure磋议,因为咱们基本上无须Azure云,是以就不先容了,感趣味趣味的不错望望源码,王人挺浅易,源码地址:https://github.com/dotnet/extensions/tree/v3.1.12/src/Configuration/Config.AzureKeyVault/src
三、IConfiguration使用
一般的,咱们要得回IConfiguration大概IConfigurationRoot,王人是连合DI容器来使用的,比如咱们的Startup:
图片
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } ... }
图片
1、在结构上,咱们不错将IConfiguration看作念一个Key-Value的围聚,另一方面,因为Key的稀少性,咱们又不错将它看作念一种树形结构的数据围聚。
这里说的Key的稀少性,指的即是Key是有层级关系的,层级秉承 ConfigurationPath.KeyDelimiter 字段符号来分隔,默许是冒号(:),不淡薄修改(秉承反射可修改)。
2、当咱们成立由改革,需要再行加载时,不错调用 IConfigurationRoot 的 Reload 措施再行加载成立
3、IConfiguration的GetSection措施不错得回某个节点信息,参数key是联系于面前节点的,其中IConfigurationSection中有三个属性:
Key:面前节点名,不包含旅途 Path:从根节点到面前节点的旅途 Value:面前节点数据
4、IConfiguration的GetConnectionString措施得回的是面前节点下的ConnectionStrings节点下指命称号子节点的数据(源码):
public static string GetConnectionString(this IConfiguration configuration, string name) { return configuration?.GetSection('ConnectionStrings')?[name]; }
5、IConfiguration有两个垂危的措施:Get和Bind。
Get措施将面前节点偏执子节点的数据调度并存放到指定类型的实体对象的属性中,并复返改实体对象。
Bind措施接纳一个实体对象,并将面前节点的偏执字节点的数据保存到改实体对象的属性中。
举个浅易的例子,比如咱们在appsettings.json 中有成立 :
图片
{ ... 'Data': { 'Value1': 1, 'Value2': 3.14, 'Value3': true, 'Value4': [ 1, 2, 3 ], 'Value5': { 'Value1': 2, 'Value2': 5.20, 'Value3': false, 'Value4': [ 4,5,6,7 ] } } }
图片
然后相对应的创建一个实体类:
图片
public class TestData { public int Value1 { get; set; } public decimal Value2 { get; set; } public bool Value3 { get; set; } public int[] Value4 { get; set; } public TestData Value5 { get; set; } }
图片
使用时的区别即是:
var section = configuration.GetSection('Data'); var data1= section.Get<TestData>(); var data2 = new TestData(); section.Bind(data2);
这么一来,经过Get措施大概Bind措施,IConfiguration中的数据就放到咱们闇练的实体对象中去了,再也无须去作念那些虚夸的字符串类型调度了!
四、回顾
这一篇就先到这里吧打屁股 调教,.net core的成立如故很浅易的,应酬望望源码就能掌捏。
本站仅提供存储工作,统统推行均由用户发布,如发现存害或侵权推行,请点击举报。热点资讯
- 2024-09-08国产自拍 东说念主到中年的鸳侣,“爱不爱”其实并不进攻
- 2024-12-10国产自拍 恩凯提亚为水晶宫出战10场英超0球0助攻,已灵通27场联赛没进球
- 2024-09-08国产自拍 聪慧的父母,王人懂得给孩子“积福”!
- 2024-09-14国产 自拍 【五绝】老师,您好!
- 2024-09-23国产自拍 官方:安德莱赫特晓喻租出维拉中场登东克尔
- 2024-11-04校园春色 自拍偷拍 沪媒:申花现在收获已超预期,斯卢茨基打造下迫切体系分解改不雅
相关资讯
- 国产自拍 9月10日华正转债下降3.13%,转股溢价率60.53%
- cos 足交 拿高薪、玩概括的冰岛老登,作念出了目前最佳玩的二战卡牌游戏?
- 国产自拍 2024年10月2日世界主要批发阛阓青冬瓜价钱行情
- 丝袜 色情 离开广东男篮, 沃特斯变化真大, 这个作为太暖了!
- 国产自拍 珍摄灰犀牛:以伊危急升级不成淡薄!投行看油价试100好意思元?石油危急