在.NET中,配置系统的核心作用是让我们的应用程序能够从外部读取设置。 在C#中,我们通常使用 JSON 文件作为这个“设置单”的格式,这个文件叫 appsettings.json。 这是一个普通的文本文件,放在项目根目录下。 它用大括号组织信息,里面是“键值对” “键”是设置的名字 “值”是具体内容 项目一创建,Visual Studio 通常会自动生成这个文件。 JSON文件里的配置是以“段”和“键”的形式嵌套组织的,用冒号“:”来代表层级关系。 配置不是一张平面的清单,而像一棵倒过来的树。比如要存“数据库”这个大类下的“连接字符串”这个具体值,在JSON里是这么写的: { "Database": { "ConnectionString": "Server=..." } } 但在代码里去找这个值的时候,我们把它展开写成一串,就是 "Database:ConnectionString"。 冒号表示“里面的”,这样就能精确找到你想要的那个具体设置了。 接下来是读取数据 读取配置之前,必须先“构建”一个配置对象,这个对象叫 IConfiguration。 代码没法直接看懂 JSON 文件里的字,得先有一个东西把文件内容读进来、整理好,变成一个程序能随时查阅的内存对象。 这个被构建出来的东西,它的类型就叫 IConfiguration。后面你想查任何一项设置,都是通过它来完成的。 构建这个 IConfiguration 对象用的是 ConfigurationBuilder 类。 ConfigurationBuilder 是“施工队”,负责把各种配置源拼装成一个 IConfiguration。 这个施工队很灵活,你可以告诉它:“先去读 appsettings.json,再去读环境变量,再去读命令行参数”。 施工队按你指定的顺序,一个一个把它们加载进来,最后打包成一个完整的 IConfiguration 交给你。 顺序很重要——后面的会覆盖前面同名的。 在实际项目中,你通常不需要手动去 new 这个施工队(ConfigurationBuilder),Web主机在启动时已经帮你构建好了。 WebApplication.CreateBuilder(args) 一行代码就替你完成了配置构建。 你会在 Program.cs 里看到这一行。这行背后,微软的框架已经自动调用了 ConfigurationBuilder,并按约定加载了 appsettings.json、环境变量等常用配置源。你拿来直接用就行,不必从零开始造车子。 好,说了这么多,来个小题,看看是否理解了 这句话对还是错?说出你的理由 appsettings.json 文件里的配置是唯一的配置来源,程序不能从其他地方读取配置。 答案:(略)(bushi) ✖ 理由: 1. appsettings.json 只是默认约定,不是唯一来源。 2. 真正决定读哪些配置的,是你在代码里指定的配置源,你可以加环境变量、命令行参数、甚至数据库。 好,我们继续 框架自动构建好的那个 IConfiguration 对象,可以通过 builder.Configuration 来访问。 也就是在 Program.cs 里,用 builder.Configuration 就能拿到配置对象。 还记得 WebApplication.CreateBuilder(args) 返回的那个 builder 吗?它身上有个 Configuration 属性,就是已经构建好的 IConfiguration。如果你想在启动阶段读某个配置(比如端口号),就在这上面操作。 那么怎么操作呢? 用索引器([ ])直接取值,像查字典一样。 var value = builder.Configuration["Database:ConnectionString"]; 冒号表示层级,和前面说的 JSON 嵌套结构对应。 这行代码的意思是:去配置里找到 Database 这个段下面的 ConnectionString,把它的值取出来给我。 但记住,取出来的都是字符串类型。如果你需要数字或布尔值等其他类型,得自己转换。 那么好,来个小练习 假设你的 appsettings.json 里有这么一段: { "App": { "Name": "MyApp", "Version": 2 } } 请写出代码,取出 Name 的值。 答案: var value = builder.Configuration["App:Name"]; 如果你真的去VS手动写并且写对了,那么你很棒,已经学会基本的用法了 接下来看第二种方式 用 GetSection 先定位到一个段,再往下取。 人话:先找到“章节”,再读里面的“条目” 有时我们不想每次都写很长的键名,可以先拿到这个段,像这样: { "666": { "666a": "aaa", "666b": 123456 } } var appSection = builder.Configuration.GetSection("666"); var name = appSection["666a"]; var version = appSection["666b"]; GetSection 返回的还是同一个类型,所以你可以继续用方括号往下取值。这在配置层级很深、或者要取同一个段下多个值的时候很实用。 然后我们再来一个练习 请用 GetSection 的方式,先拿到 App 段,再取出 Version 的值。两行代码。 { "App": { "Name": "MyApp", "Version": 2 } } 答案 var appSection = builder.Configuration.GetSection("App"); var version = appSection["Version"]; 很棒,你已经了解了如何从段取值 我们继续 用索引器([ ])取出来的值永远是 string 类型,如果配置不存在则返回 null。 注意类型转换,并且要处理“没配这个值”的情况。 比如刚才取的 666b,它其实是在 JSON 里写的数字 123456,但经过配置系统读出来后,就变成了字符串 "123456"。如果你需要整数运算,就得自己用 int.Parse 转换。 另外,万一有人把 666b 删了,取值就会返回 null,代码要做好判断。 恭喜你,坚持到了本节的结尾部分,接下来要打boss了。 打boss前,先来吃点buff 小总结: 现在说到的,是配置系统最核心的基础链路: 基础概念 配置是什么:程序外部的“设置单”,不在代码里写死 配置放哪里:默认是 appsettings.json,但不限于它 怎么组织:用“段”嵌套,冒号 : 表示层级关系 谁负责读:ConfigurationBuilder 施工队,加载多个配置源 怎么拿到:框架自动构建好,用 builder.Configuration 访问 怎么取值:两种方式:索引器 ["段:键"] 或者先 GetSection 再取值 值的类型:永远是 string,没配到返回 null 这些概念一定要清楚,这关系到以后还能不能打过更高级的怪 BOSS: 假设你有这样一个 appsettings.json: { "GameSettings": { "Title": "Space Adventure", "MaxPlayers": 4, "EnableSound": true } } 请完成以下题目: 1: 写一行代码,直接取出 Title 的值。 2: 用 GetSection 的方式,两行代码取出 MaxPlayers 的值。 3: 判断题——“取出来的 MaxPlayers 可以直接做加法运算,不需要转换。” 这句话对吗?为什么? 4: 假设 EnableSound 这个配置项被删掉了。写出代码判断它是否存在,如果不存在就输出一句“音效设置缺失”。 答案 (1) var title = builder.Configuration["GameSettings:Title"]; 或者 var title = builder.Configuration.GetSection("GameSettings")["Title"]; 都可以 如果独自写出第二种,那么你真的很厉害,已经举一反三了,尝试了两种方式的组合技。 (2) var gameSettings = builder.Configuration.GetSection("GameSettings"); var maxPlayer = gameSettings["MaxPlayers"]; (3) ✖ 从json取出来的都是字符串,必须先转换成能进行加法运算的类型 (4) var gameSettings = builder.Configuration.GetSection("GameSettings"); var enableSound = gameSettings["EnableSound"]; if (enableSound == null) { Console.WriteLine("音效设置缺失"); } 如果你都写对了,恭喜你,已经完全达成了我们这一节的目标: 能用索引器一行取值 能用 GetSection 先定位段再取值 知道取出的值必须判断 null 和转换类型 你已经被强化了,快去送(bushi) 下节预告 (二)强类型绑定与 Options 模式 别看名字怪高级,实际上就那么点事~
(一)手动取值 / 字典式读取
以下为完整正文内容。
正文
搜索结果
请输入关键词开始搜索。