为什么、在哪以及如何使用.NET配置文件?

2,449 阅读7分钟

.Net 配置文件概览

本文提供了 .NET 配置文件的快速概览,及了解更深入信息的链接。

更新:世界一直在前进。本文中的大部分信息现已过时。首选的配置机制现在位于 NuGet 的 Microsoft.Extensions.Configuration 及相关包中。有关更多的详细内容,请参阅此链接中的 ConfigurationBuilder 类的文档。

介绍

已经使用 .NET 配置文件很多年了,如果我能够提供一个有关的快速介绍,可能会给别人带来很大帮助。

在本文中,有许多的 C# 代码示例,假设您在项目中包含了对 System.Configuration.dll 的引用,并且在代码中添加了以下 using 语句:

using System.Configuration;

要想使用可以访问配置信息的 ConfigurationManager 类,必须满足这两个前提条件。

为什么

.NET Framework 提供了一组丰富的类和技术来简化应用程序的配置。本质上,所有的这些类都使从 XML 配置文件读取和写入配置信息变得更容易。

配置文件包括许多标准的节(译注:section,通常在配置文件中一个配置项表示一个section,在翻译习惯上通常称为“节”),用于常见 .NET 功能的自定义节,以及允许开发人员创建自己的自定义配置节。

标准节随着时间的推移而一直发生着改变。最初,标椎配置主要通过 appSettings 节完成,包含了每个设置的 name/value 对。而后来,通过生成的 C# Settings 类,及对应的 applicationSettingsuserSettings 配置节,向配置提供了透明、类型安全的支持。

在哪(存储位置)

在哪可以发现配置文件?这是一个看似很复杂的问题。由于配置是分层的,所以可能会有多个配置文件影响一个应用程序。其中包括机器配置文件、应用(或web)配置文件、用户本地设置文件和用户漫游设置文件。

机器配置

机器配置文件与不太容易找到的 .NET Framework 文件放在一起。配置文件的位置取决于应用程序使用的 .NET 版本和平台类型(例如 64 位)。

一个典型的示例,可能是 C:\Windows\Microsoft.NET\Framework\v4.0.30319\CONFIG\machine.config

在 C# 应用程序中,下面的代码可以返回该文件的位置:

System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() 
               + @"CONFIG\machine.config"

应用程序配置

应用程序配置文件通常与应用程序位于同一目录中。对于 Web 应用程序,它被命名为 Web.config。对于非 Web 应用程序,开始的名称是 App.config 。在构建之后,它被复制为与 .exe 文件相同的名称。因此,对于程序 MyProgram.exe,你可以在同一目录中找到 MyProgram.exe.config

在 C# 应用程序中,下面的代码可以返回该文件的位置:

AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

然而通常不建议这样做,因为,你可能会发现某些程序更改了应用程序配置文件的位置,如下所示:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "NewName.config")

用户设置

用户设置文件几乎不可能找到,也许是故意这样设计的。其目录的名称因 Windows 版本而异。更复杂的是,父文件夹通常是隐藏的。文件夹目录中还包含公司名称(应用程序供应商)、应用程序名称、应用程序的唯一标识和应用程序版本。

一个 Windows 7 上关于本地用户设置的示例可能是这样的:

C:\Users\MyUsername\AppData\Local\CompanyName\MyProgram.exe_Url_pnbmzrpiumd43n0cw05z2h4o23fdxzkn\1.0.0.0\user.config

在下面的 C# 代码中,你可以获取本地用户设置(第一行)和漫游用户设置(第二行)的基目录:

Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

在如下的 C# 代码中,可以获得本地用户设置(第一行)和漫游用户设置(第二行)的确切文件路径:

ConfigurationManager.OpenExeConfiguration
                     (ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming).FilePath

其他配置

如果这还不够令人困惑,还可以了解一些其他文件。比如根级别的 Web.config(位于与 machine.config 相同的目录中)。此外,Web 应用程序的子目录可以通过特定于该子目录的 Web.config ,对继承的设置进行额外重写。

最后,IIS 提供了一些它自己的配置。典型的位置是:C:\Windows\System32\inetsrv\ApplicationHost.config

如何使用

如之前所述,应用程序配置文件被分成许多类似标准的配置节。在这里,我们简要讨论一些最常见的配置节。

appSettings 节

最简单的标准配置节是 appSettings,包含每个设置对应的 name/value 对的集合:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="MySetting" value="MySettingValue" />
  </appSettings>
</configuration>

在 C# 中,可以使用如下方式引用设置的值:

string mySetting = ConfigurationManager.AppSettings["MySetting"];

connectionStrings 节

由于数据库连接在 .NET 中非常常见,因此为数据库连接字符串提供了一个特殊的配置节,即 connectionStrings

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="MyConnectionStringName"
      connectionString="Data Source=localhost;Initial Catalog=MyDatabase;
                        Integrated Security=True"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

在 C# 中,可以使用如下代码获取连接字符串:

string connectionString = ConfigurationManager.ConnectionStrings[
  "MyConnectionStringName"].ConnectionString;

最初,人们可能不知道是否需要引用“连接字符串”的 ConnectionString 属性。实际 connectionStrings 节的名称很糟糕。更好的名称应该是 connectionStringSettings,因为每条记录都包含一个连接字符串和一个数据库提供程序。

连接字符串的语法完全由数据库提供程序决定。在本例中,System.Data.SqlClient 是 Microsoft SQL Server 数据库最常见的数据库提供程序。

applicationSettings 和 userSettings 节

在 .NET 2.0 中,Microsoft 试图使配置文件的使用变得更加容易。因此,引入了一个设置文件。细心的观察者会注意到,“设置”首先位于应用程序配置文件中,然后被复制到用户设置的配置文件里。

对于 Windows 窗体和 WPF 应用程序,可以在项目的 Properties 文件夹中找到一个 Settings.settings 文件。对于控制台和其他应用程序,同样可以使用这个设置。打开项目的属性,然后单击 设置 按钮/选项卡。将会看到添加默认设置文件的选项。

译者注,如下为项目“属性”-“设置”中添加默认设置文件的截图:

通常,只需编辑此设置文件(或项目的设置)而不是直接编辑配置文件。下面的示例仅用于演示这些设置确实存在于配置文件中。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="userSettings"
      type="System.Configuration.UserSettingsGroup, System, 
      Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="WinFormConfigTest.Properties.Settings"
        type="System.Configuration.ClientSettingsSection, System, 
        Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        allowExeDefinition="MachineToLocalUser"
        requirePermission="false" />
    </sectionGroup>
    <sectionGroup name="applicationSettings"
       type="System.Configuration.ApplicationSettingsGroup, System, 
       Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="WinFormConfigTest.Properties.Settings"
        type="System.Configuration.ClientSettingsSection, System, 
        Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        requirePermission="false" />
    </sectionGroup>
  </configSections>
  <userSettings>
    <WinFormConfigTest.Properties.Settings>
      <setting name="MyUserSetting" serializeAs="String">
        <value>MyUserSettingValue</value>
      </setting>
    </WinFormConfigTest.Properties.Settings>
  </userSettings>
  <applicationSettings>
    <WinFormConfigTest.Properties.Settings>
      <setting name="MyApplicationSetting" serializeAs="String">
        <value>MyApplicationSettingValue</value>
      </setting>
    </WinFormConfigTest.Properties.Settings>
  </applicationSettings>
</configuration>

要引用其中的设置项,只需使用自动创建的 Settings 类。如下所示是一个典型的参考:

string myUserSetting = Properties.Settings.Default.MyUserSetting;
string myApplicationSetting = Properties.Settings.Default.MyApplicationSetting;

注意Properties 是在你的应用程序名的空间中自动创建的命名空间。

要改变用户的设置,只需给该属性指定一个值并保存更改,如下所示:

Properties.Settings.Default.MyUserSetting = newValueForMyUserSetting;
Properties.Settings.Default.Save();

更新设置

最后,还要发布应用程序的新版本。此时,你可能会遇到一个常见的问题。由于用户设置是特定于版本的,它们将会在升级后丢失。

值得庆幸的是,该框架预见到了这一需求并提供了升级方法。处理此问题的典型方式是用户设置的布尔值属性 Upgraded,初始值为 false(首次部署应用程序时)。

因此,处理升级(并保留以前的用户设置)的典型代码如下所示:

if (!Properties.Settings.Default.Upgraded)
{
  Properties.Settings.Default.Upgrade();
  Properties.Settings.Default.Upgraded = true;
  Properties.Settings.Default.Save();
}

下一步是什么

在上一部分,你可能已经注意到配置文件中相当冗长的 configSections 节。这就是 Microsoft 扩展配置文件添加新的 userSettingsapplicationSettings 节的方式。

这也是你可以添加你自己的自定义配置节的方式。

简而言之,你可以通过扩展 ConfigurationSectionConfigurationElement 类来实现这一点。在每个派生类中,你将使用 ConfigurationPropertyAttribute 之类的属性来修饰成员。

简单吧?开个玩笑。其他人对这个稍微复杂但不太困难的机制提供了很好的描述。在本文的末尾提供了链接以供进一步阅读。

此处,我只想提供一些提示,这些提示可能会在较长的描述中被忽略。

全部完成后,你需要创建一个 XML 架构的文档(XML Schema Document —— XSD 文件)用于描述你的节,并将其包含在项目中。打开配置文件后,你可以使用 XML...Schemas 菜单项来确保智能提示找到 XSD 文件。

取决于 Visual Studio 的版本,你可能会听到有关配置节的 xmlns 属性的抱怨。如果你遇到了,这有一个简单的解决方案。我通常从我自己的中间类 XmlnsConfigurationSection 派生,而不是直接从 ConfigurationSection 派生。这使得问题不会出现。

using System.Configuration;

namespace Extras.Configuration
{
  abstract public class XmlnsConfigurationSection : ConfigurationSection
  {
    [ConfigurationProperty("xmlns")]
    public string Xmlns
    {
      get { return (string)this["xmlns"]; }
      set { this["xmlns"] = value; }
    }
  }
}

深入阅读