介绍
在C#中,有两种配置文件的机制,分别是用户配置文件和应用程序配置文件,它们分别对应产生user.config
和app.config
文件。
这两种机制的主要区别在于:
- 存储位置:应用程序配置文件位于应用程序的根目录下,而用户配置文件位于用户的应用程序数据文件夹下。因此,用户配置文件是与具体用户相关的,而应用程序配置文件是与应用程序相关的。
- 读写权限:应用程序配置文件是只读的,而用户配置文件是可写的。因此,在应用程序配置文件中存储的配置信息是全局的,只能在应用程序部署时进行修改,而在用户配置文件中存储的配置信息是与具体用户相关的,可以在运行时根据用户的偏好进行修改。
- 使用方式:应用程序配置文件主要用于存储应用程序的全局配置信息,而用户配置文件主要用于存储用户的偏好设置。在代码中,可以使用ConfigurationManager类来读取应用程序配置文件中的配置信息,而使用Settings类来读取和写入用户配置文件中的配置信息。
user.config
用户配置文件(user.config)是用于存储应用程序的用户配置信息,例如窗口尺寸、字体样式、颜色方案等等。用户配置文件通常位于用户的应用程序数据文件夹下,并且是可写的。在Visual Studio中,可以使用“项目属性”窗口来定义这些用户配置信息,系统会自动生成一个Settings.settings文件,并在运行时自动创建和维护相应的user.config文件。在代码中,可以使用Settings类来读取和写入用户配置文件中的配置信息。
ApplicationSettingsBase 类可以用于管理应用程序的设置,通过使用 ApplicationSettingsBase 类,我们可以轻松地读取和写入应用程序级别的设置,而无需编写大量的代码来实现这些功能。
要使用 ApplicationSettingsBase,通常需要创建一个自定义设置类,该类继承自 ApplicationSettingsBase。在自定义设置类中,可以定义代表应用程序可配置设置的属性。通过使用 [DefaultSettingValue]
或[UserScopedSetting]
等属性,可以为每个设置项指定默认值和作用域。
先看一个简单的例子:
1 | using System.Configuration; |
运行后会发生异常
1 | The settings property 'IsActive' was not found. |
因为使用它需要几个基本条件:
- 属性访问权限必须是
public
。 - 必须提供范围注解:
[UserScopedSetting]
或者[ApplicationScopedSetting]
。 - 必须提供默认值。
1
2
3
4
5
6
7
8
9
10internal class AppSettings : ApplicationSettingsBase
{
[ ]
[ ]
public bool IsActive
{
get => (bool)this[nameof(IsActive)];
set => this[nameof(IsActive)] = value;
}
}
用户级设置
UserScopedSetting 注解表示这个属性是用户级的设置。
所谓用户级的设置,是指属性存储在当前进程用户的相关位置,该设置不会与其他用户共享设置。
1 | internal class AppSettings : ApplicationSettingsBase |
使用方法
1 | var settings = new AppSettings(); |
调用 Save 方法后会持久化设置(仅会保存用户设置)。
配置文件在哪个位置呢?可以使用这段代码查看
1 | public static string GetDefaultExeConfigPath(ConfigurationUserLevel userLevel) |
得到的路径大概是这样:
1 | C:\Users\Admin\AppData\Local\MyCompany\MyApp_Url_lab5ev2xnbcazbd33m1aiehm2mtop5ce\1.0.0.0\user.config |
存储到 Roaming 目录
默认情况下属性将存储在当前用户目录下,如果要存储到Roaming
目录,需要使用 SettingsManageability 标注。
1 | internal class AppSettings : ApplicationSettingsBase |
这样配置文件路径将会在:
1 | C:\Users\Admin\AppData\Roaming\... |
应用级设置
与用户级设置对应的是应用级的设置,用 ApplicationScopedSetting 注解类标注。
应用级的设置是不可以持久化的,默认值就是属性注解中的值。
存储位置
user.config
文件的完整路径如下所示:
1 | <Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config |
其中,不同部分的含义如下:
<Profile Directory>
:用户的应用程序数据目录,对应环境变量%LOCALAPPDATA%
,如C:\Users\<UserName>\AppData\Local
。<Company Name>
:公司名称,通常是应用程序开发者的公司名或组织名。<App Name>
:应用程序名称,指示具体的应用程序。<Evidence Type>
和<Evidence Hash>
:这些是关于应用程序证据(Evidence)的信息,用于标识不同应用程序的实例。证据信息可以包括应用程序的启动路径、域名等。这有助于区分不同实例的应用程序,以防止设置的冲突。<Version>
:应用程序的版本号,用于标识当前设置的版本。
升级文件
微软考虑的非常细致,在user.config
路径中还有程序版本,这样当有多个版本的程序共存时,不会互相干扰。
但为了新版本的程序在首次运行时能够获取到旧的设置,需要先将设置文件升级
1 | var configPath = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath; |
设置提供程序
ApplicationSettingsBase 自身不保留也不加载设置,而是由设置提供程序(派生自 SettingsProvider 的类)完成。
如果 ApplicationSettingsBase 的派生类未通过 SettingsProviderAttribute 指定设置提供程序,则默认使用提供程序 LocalFileSettingsProvider。
一个最小的自定义提供程序的例子:
1 | using System.Collections.Specialized; |
然后通过 SettingsProviderAttribute 注解标注
1 | [ ] |
除非是自己需要完全控制配置文件的格式或文件路径,所以一般不需要自己实现。
自己实现提供程序需要考虑安全、版本等问题,比较繁琐。默认的LocalFileSettingsProvider
已经足够应付绝大多数场景。
官方的实现 Settings
微软在 Visual Studio 中提供了对ApplicationSettingsBase
的包装,并支持可视化操作,它就是Settings.settings
文件。
创建文件:可以在 Visual Studio 中右击项目,选择 “Add”(添加) -> “New Item”(新建项),然后选择 “Settings File”(设置文件)。
VS会工程目录下生成3个文件
1 | Settings.cs |
- 双击
Settings.settings
文件可以进行设置的可视化编辑。 Settings.Designer.cs
文件是由编辑Settings.settings
自动生成的,我们不应该修改它。Settings.cs
文件下有一个名为Settings
的类,这里的代码是可以编辑的。
这个类继承自ApplicationSettingsBase
,实行了单例模式,在程序直接使用即可。所以在实际开发中,我们按照微软的实践来即可,通常情况下不需要自己去实现ApplicationSettingsBase
。
实现自定义的类型
在VS中编辑设置的类型,只有一些如string等等的内置类型,如果要实现自己的类型如何做呢?这就需要用到 TypeConverter。
在 VS2022 中,类型
的下拉框并没有自定义选项,所以需要手动编辑Settings.settings
文件
1 |
|
将Type
属性修改为自定义类型的完全限定名。并且实现自己的TypeConverter
。一个简单的例子
1 | [ ] |
本质上,就是处理字符串与自定义类型之间的转换过程。
app.config
应用程序配置文件(app.config)是一个XML文件,用于存储应用程序的全局配置信息,例如数据库连接字符串、日志级别、应用程序设置等等。应用程序配置文件通常位于应用程序的根目录下,并且是只读的。在代码中,可以使用 ConfigurationManager 类来读取应用程序配置文件中的配置信息。
按照以下步骤来创建app.config文件:
- 右键单击项目名称,选择“添加”->“新建项”菜单项。
- 在“添加新项”对话框中,选择“应用程序配置文件”模板,并指定文件名为“app.config”。
文件内容:
1 |
|
你可以在其中添加配置信息。在app.config文件中添加配置信息,例如数据库连接字符串、日志级别、应用程序设置等等,并在代码中使用 ConfigurationManager 类来读取app.config文件中的配置信息。
AppSettings和ConnectionStrings属性
微软在 ConfigurationManager 上安排了两个属性:
分别对应文件中AppSettingsSection
和ConnectionStringsSection
两个配置节,用于存储应用程序的常规设置和数据库连接字符串信息。
AppSettingsSection 配置节用于存储应用程序的常规设置,例如日志级别、应用程序设置等等,例如:
1 | <appSettings> |
ConnectionStringsSection 配置节用于存储应用程序的数据库连接字符串信息,例如:
1 | <connectionStrings> |
在代码中,可以使用 ConfigurationManager 类来读取 app.config 文件中的配置信息。例如,以下代码演示了如何读取名为”LogLevel”的应用程序设置和名为”MyDB”的数据库连接字符串:
1 | string logLevel = ConfigurationManager.AppSettings["LogLevel"]; |
自定义Section
使用自定义配置节之前,我们需要在app.config
中注册该配置节(在<configSections>
下定义),以便应用程序能够识别并正确地读取该配置节。
1 | <configuration> |
- name:自定义配置节的名称。
- type:自定义配置节的类型,C#提供了
System.Configuration.SingleTagSectionHandler
、System.Configuration.DictionarySectionHandler
、System.Configuration.NameValueSectionHandler
等等常用的节类型。
使用很简单
1 | var section = (NameValueCollection)System.Configuration.ConfigurationManager.GetSection("MySettings"); |
键值对类型的选项可以用官方提供的 NameValueSectionHandler。
但如果需要更复杂的类型,可以实现自己的节类,它应该继承自 ConfigurationSection。
1 | public class MyCustomSection : ConfigurationSection |
然后在 app.config 文件中添加一个名为”MyCustomSection”的自定义配置节:
1 | <configuration> |
注意type
中的格式,前面是自定义节类型的完全名称,然后用逗号分隔,逗号后是程序集的名称。
这样就能得到一个自定义的类实例:
1 | var mySection = ConfigurationManager.GetSection("MyCustomSection") as MyCustomSection; |
如果设置节还有子类型的话也是可以做到的,更高级的用法可以自行查阅相关资料,本文就不展开了。
总结
当项目中有 app.config 文件时,对 .settings 的编辑会自动同步到 app.config 文件中。同步过去的应用范围设置会在applicationSettings
节点。而通过ConfigurationManager.AppSettings['key']
这种方式访问的是<appSettings>
节点,且总是字符串类型。所以我有理由相信,在今天,已经不推荐用这种方式了。
在VS中,对 .settings 支持更多,可以可视化编辑、自动生成相关代码,是强类型的。
所以在实际开发中,建议通过 .settings 来管理设置。如果需要给用户编辑应用范围设置的机会,如数据库连接字符串,那么就新建一个 app.config 文件,这样 .settings 中的应用级设置会同步过来,并且复制到程序目录,使得用户编辑成为可能。否则,就可以不需要 app.config 文件。
参考
When using a Settings.settings file in .NET, where is the config actually stored?
Keep user’s settings after altering assembly/file version
Using Settings in C#
使用微软提供的Settings以及自定义SettingsProvider
在VisualBasic2005中使用My.Settings
“设置”页面,项目设计器
应用程序设置体系结构
应用程序设置特性
在Web.config或App.config中的添加自定义配置
Using Custom Classes with Application Settings