C#怎么实现配置文件读写_C#如何读取App.config和appsettings.json【教程】
C#怎么实现配置文件读写_C#如何读取App.config和appsettings.json【教程】

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
开门见山,先说一个核心结论:App.config 在现代 .NET 开发中已经出局,而 appsettings.json 虽然是标准,但它的设计初衷是“只读”的。 这意味着,如果你想让应用在运行时动态修改配置并持久化保存,指望框架自动帮你双向同步,那可就找错方向了。真正的解决方案,是手动构建配置对象并直接操作 JSON 文件本身。
App.config 在现代 C# 项目里根本不能“写”
首先得明确,App.config 是 .NET Framework 时代的产物。那时候,大家习惯用 ConfigurationManager.AppSettings[“key”] 来读取配置,感觉挺方便。但问题在于,这个机制从设计上就是只读的。你或许尝试过修改值然后调用 Sa ve(),结果发现要么不生效,要么只在当前进程内存里变了一下,应用一重启,改动就全丢了。
到了 .NET Core / .NET 5+ 的时代,情况就更彻底了:
- 新建的 .NET 6/7/8 项目,默认根本不会包含 App.config 文件。
- 即便你手动添加一个,运行时也不会自动加载它。
- 更关键的是,即便你强行想用旧方法,比如调用
ConfigurationManager.OpenExeConfiguration,在 .NET Core+ 平台上,等待你的很可能是一个PlatformNotSupportedException异常。Visual Studio 编译时确实会把 App.config 复制为MyApp.exe.config,但运行时根本不会监听这个文件的任何变更。
所以,结论很清晰:对于新项目,App.config 这条路可以直接放弃了。
appsettings.json 只能读,不能直接写
既然 App.config 不行,那转向标准的 appsettings.json 总可以了吧?很遗憾,这里也有一个常见的误解。我们通过依赖注入拿到的 IConfiguration 接口,它提供的是 GetSection()、GetValue 等一系列读取方法,但翻遍文档,你也找不到一个官方的 Set() 或 Sa ve() 方法。
这是为什么呢?因为 IConfiguration 本质上是一个配置源的只读快照。它的背后可能串联着 JSON 文件、环境变量、命令行参数、内存字典等多个来源。这种设计是为了灵活性和优先级合并,但也意味着它没有“写回”某个特定源(比如 JSON 文件)的职责。
- 如果你试图通过一些“黑魔法”(比如强制转换类型)去修改
IConfiguration实例内部的状态,这属于未公开的行为,不同版本的 .NET SDK 可能导致不可预知的后果,甚至程序崩溃。 - 当然,你可以手动用
JsonSerializer.Serialize()把配置写回 JSON 文件,但这意味着你必须自己处理一堆麻烦事:并发写入冲突、保持 JSON 的格式缩进、处理注释丢失等等。 - 还有一个棘手的问题:如果你的配置项混合了多个来源(比如数据库连接字符串来自 appsettings.json,而日志级别来自环境变量),那么“写回文件”这个操作本身就无法还原这种复杂的来源逻辑。
所以,appsettings.json 本身不是用来“写”的,IConfiguration 也不是那个负责持久化的对象。
真要实现“可写配置”,得绕过 IConfiguration 直接操作 JSON 文件
那么,正确的姿势到底是什么?答案是:绕过 IConfiguration 的只读抽象层,直接对 appsettings.json 这个物理文件进行读写操作。 这是最可控、最可预测的方法。
具体步骤可以分解如下:
- 读取与解析:首先,使用
File.ReadAllText(“appsettings.json”)将文件内容完整读入,然后通过System.Text.Json或Newtonsoft.Json将其反序列化。你可以反序列化为灵活的JsonDocument,或者更常见的,映射到一个预先定义好的 POCO(普通C#类)模型上。 - 修改配置:在内存中修改这个模型对象的属性值,比如
settings.Logging.LogLevel.Default = “Debug”;。 - 写回与重载:使用 JSON 序列化器将修改后的对象重新序列化为字符串,并用
File.WriteAllText写回原文件。这里有个关键点:为了保持文件可读性,建议在序列化时设置WriteIndented = true。写入完成后,调用之前保存的IConfigurationRoot.Reload()方法,触发配置系统重新加载文件,使改动立即生效。
// 构建配置时,确保获取到 IConfigurationRoot 的引用
var config = new ConfigurationBuilder()
.AddJsonFile(“appsettings.json”, optional: false, reloadOnChange: true)
.Build();
var root = (IConfigurationRoot)config;
// 直接读写 JSON 文件
var settings = JsonSerializer.Deserialize(File.ReadAllText(“appsettings.json”));
settings.Logging.LogLevel.Default = “Debug”;
File.WriteAllText(“appsettings.json”, JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true }));
// 触发配置重载
root.Reload();
需要提醒的是,在写回文件前,强烈建议对原文件进行备份。这样可以防止万一序列化过程出错导致 JSON 格式损坏,从而避免应用下次启动时直接失败。
别忽略 reloadOnChange 和文件权限这两个硬限制
即使你按照上面的流程操作,还有两个底层限制必须心里有数,它们常常在部署后成为“幽灵问题”。
第一个是关于 reloadOnChange: true。这个选项依赖于 FileSystemWatcher 来监听文件变化,但它并非百分百可靠:
- 在 Docker 容器环境中,尤其是 Windows 主机搭配 Linux 容器时,挂载卷(Volume)的文件变更事件经常无法正确触发。
- 如果 appsettings.json 文件被其他进程(如 Visual Studio 正在编辑,或者记事本没有关闭)以独占方式打开,重载可能会静默失败。
第二个,也是更实际的限制,是文件系统权限。
- 在 Linux 系统上部署时,如果运行应用的用户(比如 www-data)没有对 appsettings.json 文件的读取权限,应用在启动阶段就会抛出
UnauthorizedAccessException,根本到不了运行时。 - 而“写”配置时,问题更突出:appsettings.json 通常位于应用程序集相同的目录。在生产环境中,无论是 Linux 的 systemd 服务还是 Windows 服务,其运行账户默认往往没有对该目录的写入权限。如果你没提前配置好权限,写文件时会直接抛出异常。
所以,在实现可写配置功能的同时,务必把权限检查和异常处理纳入考量范围,这才是真正稳健的做法。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
ThinkPHP事务锁表怎么解_ThinkPHP死锁排查与优化【教程】
ThinkPHP事务锁表怎么解?死锁排查与优化实战指南 先说一个核心判断:你在ThinkPHP事务中遇到的锁表或死锁问题,本质上并非框架缺陷,而是数据库底层机制、事务执行顺序与引擎配置共同作用的结果。动手改代码之前,务必先确认三件事:表引擎是不是MyISAM?是否存在未提交的长事务?是否在非更新场景
ThinkPHP多语言小程序怎么接_ThinkPHP多语言微信端解答【技巧】
ThinkPHP多语言在微信小程序中的手动控制策略 想在微信小程序里用上ThinkPHP的多语言功能?没问题,但得换换思路。它和传统的Web端有个根本区别:语言切换必须手动控制,没法依赖浏览器的自动检测机制。原因很简单,小程序环境里既没有HTTP_ACCEPT_LANGUAGE请求头,也不会自动走C
python及pycharm的安装与环境配置的过程(附详细图文)
前言 对于嵌入式、机器人开发来说,Python 往往是绕不开的核心工具。而一切学习的起点,都始于一个稳定、可靠的开发环境。今天,我们就来手把手地走一遍 Python 解释器和 PyCharm IDE 的安装全流程。从官网下载、环境配置到最终验证,每一步都配有清晰的图文说明,目标就是帮你快速、无痛地搭
SpringBoot+Disruptor实现特快高并发处理
01、背景 最近在项目里用到了Disruptor做消息队列——没错,你没看错,不是Kafka,也不是RabbitMQ。Disruptor最大的一个特点,就是快。当然,它还是开源的。这篇文章,就带你快速认识一下它,并记录一个基础的入门示例。 02、Disruptor 介绍 先来聊聊Disruptor的
mybatis动态SQL常用的标签使用及说明
1 标签 在MyBatis的动态SQL世界里,标签有个更接地气的名字——SQL片段。它的作用,说白了就是帮你把一段常用的SQL语句“打包”起来,方便在多个地方重复调用。 怎么用呢?很简单。你只需要给这个片段起一个在当前命名空间下独一无二的ID,然后在需要的地方,用标签通过这个ID把它“引入”进来就
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

