|
一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。
配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们以 Hard Code(硬编码)的方式写在应用代码中,这样配置就会很乱,而且后续也不容易修改。乱而多,而且不容易修改,这就需要一个统一管理的地方,最常见的方式就是配置文件,这个也是开发人员非常熟悉的方式。
通过配置文件设置好软件应用运行的各种参数之后,我们在开发过程中需要能够读取到配置文件的内容,根据配置内容进行软件逻辑的判断,实现完善的软件行为逻辑。这一篇就是介绍 .NET Core 框架下怎么使用配置系统,这也是 .NET Core 下的基础设施之一。
1. 配置读取
配置读取是配置系统最基本的操作,几乎是每个开发人员都会进行的操作,一个开发人员可能不清楚配置系统是怎么实现的,配置文件是怎么解析的,但一定都做过读取配置信息的操作。.NET Core 框架下对于配置系统的使用最终暴露出来的接口是 ·IConfiguration·,它是供配置数据的统一视图,配置读取就通过这个接口的实现来进行。
默认创建的 ASP .NET Core 框架模板项目中默认有一个 appsettings.json 配置文件,这个也是 ASP .NET Core 中最常用的配置文件,在配置文件中添加多一个 Settings 节点,内容如下:- {
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "AllowedHosts": "*",
- "Settings": {
- "key1": "value1",
- "key2": 1,
- "key3": true,
- "key4": {
- "subKey1": "value",
- "subKey2": 1
- },
- "items": [ "item1", "item2", "item3" ]
- }
- }
复制代码 我们要读取配置文件中的内容,例如读取“AllowedHosts”对于的值,只需要将其注入到需要的服务类中即可使用,ASP.NET Core 模板项目中使用Web主机构建和管理应用,在使用主机默认配置的时候已经将 Iconfiguration 服务注册到依赖注入容器之中。- [ApiController]
- [Route("[controller]")]
- public class WeatherForecastController : ControllerBase
- {
- private readonly IConfiguration _configuration;
- public WeatherForecastController(IConfiguration configuration)
- {
- _configuration = configuration;
- }
- [HttpGet]
- public Task Get()
- {
- var allowedHosts = _configuration["AllowedHosts"];
- Console.WriteLine(allowedHosts);
- // 配置键不区分大小写
- var allowedHosts = _configuration["AllowedHosts"];
- Console.WriteLine(allowedHosts);
- return Task.CompletedTask;
- }
- }
复制代码 上面这种读取方式是索引器方式,最简单也是基本的方式,配置被加载到内存中是以键值对的方式存在的,我们可以通过配置键读取配置值,键是字符串,不区分大小写,读取出来的值都是字符串。
配置文件中配置值往往不止一层,就像上面 appsettings.json 文件中,Logging 节点下还有子节点,如果需要这种分层数据,可以使用 : 字符(英文冒号)分隔层次结构,例如获取上面配置键 Default 对于的配置值。- // 以 : 作为分隔符,表示层级结构
- var defalutLogLevel = _configuration["Logging:LogLevel:Default"];
复制代码 如果配置值是数组,需要读取数组中具体的某一个值,可以用该值在数组中的索引作为key,例如读取上面配置文件中的items数组中的 item2。- // 读取数组,可以用值在数组中的索引作为key
- var item2 = _configuration["Settings:items:1"];
复制代码 这种方式读取配置有挺多不方便的地方,例如配置值是数值型的时候,需要我们直接转换,例如一次只能读取到一个配置值。微软通过 Microsoft.Extensions.Configuration.Binder 中的ConfigurationBinder 类提供了一些 IConfiguration 的静态方法,用于获取配置值时进行自动转换和绑定。
(1) GetValue
通过ConfigurationBinder中的GetValue扩展方法,一样可以通过配置键从配置系统中读取对于的配置值。该方法有多个重载,支持通过泛型的方式进行数据类型转换,并且支持设置默认值。- var defaultLogLevel2 = _configuration.GetValue<string>("Logging:LogLevel:Default");
- // 配置信息中不包含 "Logging:LogLevel:Default" 这个Key时,以默认值 "Error" 返回
- var defaultLogLevel3 = _configuration.GetValue<string>("Logging:LogLevel:Default", "Error");
复制代码 (2) GetSection
这样子有些情况下仍然无法满足我们的需要,某一些情况下我们会需要直接读取配置中的一部分节点,例如直接读取上面配置中的 LogLevel 部分。IConfiguration 中的 GetSection 方法可以通过 Key 直接读取某一个子节点。该方法的返回值是 IConfigurationSection 类型,永远不会返回 null,IConfigurationSection 实际上是一个 IConfiguration 的派生接口,也就是说我们还可以从 IConfigurationSection 再去获取我们需要的具体的配置值。- var section = _configuration.GetSection("Settings:key4");
- var defaultLogLevel4 = section["Default"];
复制代码 (3) Get
上面讲到通过 GetSection 获取到了配置文件中的一部分子节点,但是那样仍然不方便,还是需要一个一个去读取具体的值。可以通过 ConfigurationBinder.Get 扩展方法,将配置以强类型的方式绑定到对象上。
首先需要定义一个类来接收配置文件中的节点信息- public class KeyOptions
- {
- public string subKey1 { get; set
- public int subKey2 { get; set; }
- }
复制代码 然后通过以下方式进行绑定:- var keyOption1 = _configuration.GetSection("Settings:key4").Get<KeyOptions>();
复制代码 (4) Bind
ConfigurationBinder.Bind 扩展方法与 Get 方法类似,也是用于将配置绑定为强类型对象,不过Bind的方法是绑定到一个已实例化的对象上,需要提供一个已存在的对象。- var keyOption2 = new KeyOptions();
- _configuration.GetSection("Settings:key4").Bind(keyOption2);
复制代码 (5) Exists
上面说过,GetSection 方法获取配置中的子节点,返回值永远不会为 null。如果我们传入了一个不存在的key,肯定是获取不到对于的值的,这种情况下还是需要判断对于的子节点到底是不是真正存在的,这时候可以使用 Exists 方法。- var section = _configuration.GetSection("settings");
- var exist = section.Exists();
复制代码 除此之外,还有一个 GetChildren 方法,无需参数,用于获取到当前配置节点的所有直接子节点的集合。
以上就是 .NET Core 体系下配置系统读取配置的基本介绍,涉及到的类型最主要的是 IConfiguration 接口,除此之外还有上面提到的 IConfigurationSection 接口,以及 IConfigurationRoot 接口。
IConfigurationRoot 表示配置的根节点,是IConfiguration的派生接口,以下为接口的定义:- public interface IConfigurationRoot: IConfiguration{
- // 存放了当前应用程序的所有配置提供程序
- IEnumerable<IConfigurationProvider> Providers { get; }
- // 强制从配置提供程序中重载配置
- void Reload();
- }
复制代码 这里可以看到一个关键的属性 IEnumerable Providers,这个就是配置系统中的配置信息的来源,后面会仔细讲这个。而 Reload 方法中最关键的也是调用集合中各个 IConfigurationProvider 进行数据加载。
IConfigurationSection 表示配置中的子节点,也是 IConfiguration 的派生接口,以下为接口的定义:- public interface IConfigurationSection: IConfiguration{
- // 该子节点在其父节点中所表示的 key,即直接对应的key
- string Key { get; }
- // 该子节点在配置中的全路径(从根节点开始,到当前节点以:符号分隔的路径)
- string Path { get; }
- // 该子节点的 value。如果该子节点是叶子节点,则Value为该节点对于的值,若其下存在子节点,则其始终为 null
- string Value { get; set; }
- }
复制代码 IConfigurationSection 接口通过以上三个属性,结合 IConfiguration中的 GetChildren 方法来完整地表示的一个子节点,而 Exists 方法判断节点是否为空,就是针对 IConfigurationSection 中的 Value 属性和 GetChildren 方法来进行的。- public static class ConfigurationExtensions{
- public static bool Exists(thisIConfigurationSection section){
- if(section == null)
- {
- returnfalse;
- }
- returnsection.Value != null || section.GetChildren().Any();
- }
- }
复制代码
参考文章:
ASP.NET Core 中的配置 | Microsoft Learn
配置 - .NET | Microsoft Learn
理解ASP.NET Core - 配置(Configuration)
ASP.NET Core 系列:
目录:ASP.NET Core 系列总结
上一篇:ASP.NET Core - 依赖注入(四)
来源:https://www.cnblogs.com/wewant/archive/2023/03/02/17110738.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|