翼度科技»论坛 编程开发 .net 查看内容

ASP.NET Core - 配置系统之配置读取

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。
配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们以 Hard Code(硬编码)的方式写在应用代码中,这样配置就会很乱,而且后续也不容易修改。乱而多,而且不容易修改,这就需要一个统一管理的地方,最常见的方式就是配置文件,这个也是开发人员非常熟悉的方式。
通过配置文件设置好软件应用运行的各种参数之后,我们在开发过程中需要能够读取到配置文件的内容,根据配置内容进行软件逻辑的判断,实现完善的软件行为逻辑。这一篇就是介绍 .NET Core 框架下怎么使用配置系统,这也是 .NET Core 下的基础设施之一。
1. 配置读取

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

参考文章:
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】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具