一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。

配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们以 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 - 依赖注入(四)

ASP.NET Core - 配置系统之配置读取的更多相关文章

  1. [ASP.NET Core 3框架揭秘] 配置[1]:读取配置数据[上篇]

    提到"配置"二字,我想绝大部分.NET开发人员脑海中会立即浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化 ...

  2. [ASP.NET Core 3框架揭秘] 配置[2]:读取配置数据[下篇]

    [接上篇]提到“配置”二字,我想绝大部分.NET开发人员脑海中会立即浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化的配置定义 ...

  3. ASP.NET Core 从 gitlab-ci 环境变量读取配置

    最近在加强持续集成,遇到一个场景需要通过 gitlab-ci 环境变量(Settings -> Settings -> CI/CD -> Variables )在持续集成时向 ASP ...

  4. .NET Core采用的全新配置系统[10]: 配置的同步机制是如何实现的?

    配置的同步涉及到两个方面:第一,对原始的配置文件实施监控并在其发生变化之后从新加载配置:第二,配置重新加载之后及时通知应用程序进而使后者能够使用最新的配置.要了解配置同步机制的实现原理,先得从认识一个 ...

  5. [ASP.NET Core 3框架揭秘] 配置[3]:配置模型总体设计

    在<读取配置数据>([上篇],[下篇])上面一节中,我们通过实例的方式演示了几种典型的配置读取方式,接下来我们从设计的维度来重写认识配置模型.配置的编程模型涉及到三个核心对象,分别通过三个 ...

  6. [ASP.NET Core 3框架揭秘] 配置[7]:多样化的配置源[中篇]

    物理文件是我们最常用到的原始配置载体,而最佳的配置文件格式主要有三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonConfigurationSource.XmlConfigura ...

  7. [ASP.NET Core 3框架揭秘] 配置[6]:多样化的配置源[上篇]

    .NET Core采用的这个全新的配置模型的一个主要的特点就是对多种不同配置源的支持.我们可以将内存变量.命令行参数.环境变量和物理文件作为原始配置数据的来源.如果采用物理文件作为配置源,我们可以选择 ...

  8. [ASP.NET Core 3框架揭秘] 配置[5]:配置数据与数据源的实时同步

    在<配置模型总体设计>介绍配置模型核心对象的时候,我们刻意回避了与配置同步相关的API,现在我们利用一个独立文章来专门讨论这个话题.配置的同步涉及到两个方面:第一,对原始的配置源实施监控并 ...

  9. [ASP.NET Core 3框架揭秘] 配置[4]:将配置绑定为对象

    虽然应用程序可以直接利用通过IConfigurationBuilder对象创建的IConfiguration对象来提取配置数据,但是我们更倾向于将其转换成一个POCO对象,以面向对象的方式来使用配置, ...

  10. 【ASP.NET Core】自定义的配置源

    本文的主题是简单说说如何实现 IConfigurationSource.IConfigurationProvider 接口来自定义一个配置信息的来源,后面老周给的示例是实现用 CSV 文件进行应用配置 ...

随机推荐

  1. 踩坑记录:Redis的lettuce连接池不生效

    踩坑记录:Redis的lettuce连接池不生效 一.lettuce客户端 lettuce客户端 Lettuce 和 Jedis 的都是连接Redis Server的客户端程序.Jedis在实现上是直 ...

  2. Velero 系列文章(二):使用 Helm 安装 Velero

    概述 本文是通过 Helm 3 来安装 Velero, 只做最基本的安装.并计划将 YAML (只备份 YAML, 不备份 Volume) 备份到腾讯云的 COS(兼容 S3, 所以可以通过 AWS ...

  3. 《HTTP权威指南》– 7.缓存

    Web缓存的概念 Web缓存是可以自动保存常见文档副本的HTTP设备. 使用缓存的优点: 减少了数据的数据传输,节省了网络费用: 缓解了网络瓶颈的问题,不需要更多的带宽就能更快地加载页面: 降低了原始 ...

  4. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(36)-掌握Fiddler中Fiddler Script用法,你会有多牛逼-上篇

    1.简介 Fiddler是一款强大的HTTP抓包工具,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有 ...

  5. Go DevOps大厂运维平台开发进阶实战营

    使用 Jenkinsfile 创建流水线已报名老男孩运维课,见底下评论.enkinsfile 是一个文本文件,它包含 Jenkins 流水线的定义,并被检入源代码控制仓库.Jenkinsfile 将整 ...

  6. uniapp微信小程序返回上一页并刷新数据

    根据要求:详情页返回列表页时,要刷新列表页的数据,操作如下 @click="goBack" goBack{ let pages = getCurrentPages(); // 当前 ...

  7. 使用动态输出打印内核的DEBUG信息

    简介 printk()是很多嵌入式开发者喜欢用的调试手段之一,但是,使用printk()每次都要重新编译内核,很不方便.使用动态输出在不需要重新编译内核的情况下,方便的打印出内核的debug信息. 要 ...

  8. 代码小DEMO随笔---JS原生手机版本alert弹框

    之前的随笔写的是WEB版本的弹框,这次是手机版本,欢迎路过的大佬们提出更好的写法~~ <!DOCTYPE html> <html lang="en"> &l ...

  9. Jemeter参数

    以下是转载内容,仔细看过后,觉得用得最多的应该是csvread函数.用户自定义变量以及CSV DATA CONFIG控制器这几个,但是做练习之后,在结果树和聚合报告中怎么查看执行结果是个问题,没找到对 ...

  10. Docker修改已有容器的端口映射

    Docker修改已有容器的端口映射 背景 拉取了jenkins的镜像,启动容器的时候端口就映射了8080,但这个演示环境要用到jenkins node,其中默认的代理端口是50000.漏了,就想着能否 ...