引言:一个困扰每位 .NET 开发人员的问题
\n\n您是否曾想过,当您写下 ConfigurationManager.AppSettings["myKey"] 时,实际发生了什么?大多数开发人员只是将其视为理所当然:写一行代码,得到一个值。但如果您深入挖掘(这正是每个好奇的人在阅读 Stack Overflow 上的热门问题后所做的),您会发现这个简单调用背后隐藏着一整套机制。
在本文中,我们不仅会展示如何在 C# 中从 app.config 或 web.config 读取设置。我们还将“深入剖析”:分析 .NET Framework 如何解析 XML,哪些类参与了这一过程,以及为什么有时您的设置无法读取(剧透:不仅仅是缓存的错)。
\n\n如果您曾经遇到过 ConfigurationManager.AppSettings["ConnectionString"] 返回 null,而配置文件就在旁边的情况,那么本文就是为您准备的。
1. 基础:配置文件的结构
\n\n在深入探讨之前,让我们回顾一下典型的 app.config(或 web.config)是什么样子的。一切从根元素 <configuration> 开始:
<?xml version="1.0" encoding="utf-8" ?>\n<configuration>\n <appSettings>\n <add key="ApiUrl" value="https://api.example.com"/>\n <add key="TimeoutSeconds" value="30"/>\n </appSettings>\n <connectionStrings>\n <add name="MainDb" connectionString="Server=.;Database=MyDb;Trusted_Connection=true;"/>\n </connectionStrings>\n</configuration>\n\n这个 XML 文件不仅仅是一组字符串。它是一个严格类型化的结构,.NET 以特殊方式对其进行解释。而有趣的部分就从这里开始。
\n\n2. ConfigurationManager 的工作原理:从调用到结果
\n\n当您调用 ConfigurationManager.AppSettings["ApiUrl"] 时,会发生以下事件链:
- \n
- 确定配置文件。 系统确定要读取哪个文件。对于应用程序,它是
YourApp.exe.config(位于 exe 文件旁边);对于 Web 应用程序,它是根目录下的web.config。如果文件不存在,则返回一个空集合。 \n - 加载 XML。 文件作为 XML 文档被读取。使用
System.Xml.XmlDocument或更高效的XmlReader(取决于 .NET 版本)。 \n - 查找节。 查找
<configuration>元素,然后在其内部查找<appSettings>。 \n - 解析值。 每个带有
key和value属性的子元素<add>被转换为键值对,并放入NameValueCollection中。 \n - 缓存。 结果被缓存。再次调用
ConfigurationManager.AppSettings不会重新读取文件,而是从缓存中获取数据。 \n
重要细节:缓存与更改
\n\n如果您在应用程序运行时更改了 app.config,ConfigurationManager.AppSettings 将不会看到这些更改,直到应用程序域被重新加载。这是最常见的错误原因之一:“我更改了设置,但程序仍然使用旧值!”
要强制重新读取配置,可以使用 ConfigurationManager.RefreshSection("appSettings"),但这更像是一种权宜之计,而非解决方案。
3. 节处理程序:自定义节
\n\n您可能已经注意到,在 web.config 中不仅有 appSettings,还有 system.web、system.net 等。每个这样的节都由其自己的 节处理程序 处理——一个负责