应用程序设置体系结构
本主题介绍应用程序设置体系结构的工作原理,并探索体系结构的高级功能,例如分组设置和设置键。
应用程序设置体系结构支持使用应用程序或用户范围定义强类型的设置,并在应用程序会话之间持久化这些设置。 该体系结构提供默认持久性引擎,用于保存设置并将其从本地文件系统加载。 该体系结构还定义了用于提供自定义持久性引擎的接口。
应用程序提供了接口,使自定义组件在被托管时可以保留其自身的设置。 通过使用设置键,组件可以保留组件多个实例的设置分开。
定义设置
应用程序设置体系结构在 ASP.NET 和 Windows 窗体中使用,并且包含跨两个环境共享的多个基类。 最重要的是 SettingsBase,它通过集合提供对设置的访问,并提供用于加载和保存设置的低级别方法。 每个环境实现派生自 SettingsBase 的自己的类,为该环境提供其他设置功能。 在基于 Windows 窗体的应用程序中,必须在派生自 ApplicationSettingsBase 类的类上定义所有应用程序设置,该类将以下功能添加到基类:
更高级别的加载和保存操作
支持用户范围的属性设置
将用户的设置还原为预定义的默认值
从以前的应用程序版本升级设置
在更改设置之前或保存设置之前验证设置
可以使用 System.Configuration 命名空间中定义的多个属性来描述这些设置;应用程序设置属性中介绍了这些属性。 定义设置时,必须使用 ApplicationScopedSettingAttribute 或 UserScopedSettingAttribute应用此设置,该设置是应用于整个应用程序还是仅适用于当前用户。
下面的代码示例使用单个设置定义自定义设置类,BackgroundColor
。
using System;
using System.Configuration;
using System.Drawing;
public class MyUserSettings : ApplicationSettingsBase
{
[UserScopedSetting()]
[DefaultSettingValue("white")]
public Color BackgroundColor
{
get
{
return ((Color)this["BackgroundColor"]);
}
set
{
this["BackgroundColor"] = (Color)value;
}
}
}
Imports System.Configuration
Public Class MyUserSettings
Inherits ApplicationSettingsBase
<UserScopedSetting()> _
<DefaultSettingValue("white")> _
Public Property BackgroundColor() As Color
Get
BackgroundColor = Me("BackgroundColor")
End Get
Set(ByVal value As Color)
Me("BackgroundColor") = value
End Set
End Property
End Class
设置持久性
ApplicationSettingsBase 类本身不会持久保存或加载设置;此作业属于设置提供程序,该类派生自 SettingsProvider。 如果派生的 ApplicationSettingsBase 类未通过 SettingsProviderAttribute指定设置提供程序,则使用默认提供程序 LocalFileSettingsProvider。
最初随 .NET Framework 一起发布的配置系统支持通过本地计算机的 machine.config 文件或在随应用程序一起部署的 app.
exe.config 文件中提供静态应用程序配置数据。 LocalFileSettingsProvider 类通过以下方式扩展对该原生支持:
应用程序范围的设置可以存储在 machine.config 或
app.
exe.config 文件中。 Machine.config 始终为只读,而app
.exe.config 因安全考虑而在大多数应用程序中限制为只读。用户范围的设置可以存储在
app
.exe.config 文件中,在这种情况下,它们被视为静态默认值。非默认用户范围设置存储在新文件中,user.config。可以使用 DefaultSettingValueAttribute为用户范围设置指定默认值。 由于用户范围的设置在应用程序执行期间经常发生更改,因此 user.config 始终是可读/写的。 有关用户范围设置存储位置的详细信息,请参阅 。
所有三个配置文件都以 XML 格式存储设置。 应用程序范围设置的顶级 XML 元素是 <appSettings>
,而 <userSettings>
用于用户范围设置。 包含应用程序范围的设置和用户范围设置默认值的 app
.exe.config 文件如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WindowsApplication1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WindowsApplication1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" />
</sectionGroup>
</configSections>
<applicationSettings>
<WindowsApplication1.Properties.Settings>
<setting name="Cursor" serializeAs="String">
<value>Default</value>
</setting>
<setting name="DoubleBuffering" serializeAs="String">
<value>False</value>
</setting>
</WindowsApplication1.Properties.Settings>
</applicationSettings>
<userSettings>
<WindowsApplication1.Properties.Settings>
<setting name="FormTitle" serializeAs="String">
<value>Form1</value>
</setting>
<setting name="FormSize" serializeAs="String">
<value>595, 536</value>
</setting>
</WindowsApplication1.Properties.Settings>
</userSettings>
</configuration>
有关配置文件的应用程序设置部分中元素的定义,请参阅 应用程序设置架构。
设置绑定
应用程序设置使用 Windows 窗体数据绑定体系结构在设置对象和组件之间提供设置更新的双向通信。 如果使用 Visual Studio 创建应用程序设置并将其分配给组件属性,则自动生成这些绑定。
只能将应用程序设置绑定到支持 IBindableComponent 接口的组件。 此外,组件必须为特定的绑定属性实现更改事件,或者通知应用程序设置通过 INotifyPropertyChanged 接口更改了该属性。 如果组件未实现 IBindableComponent 并且通过 Visual Studio 绑定,则首次设置绑定属性,但不会更新。 如果组件实现 IBindableComponent 但不支持属性更改通知,则更改属性时,绑定将不会在设置文件中更新。
某些 Windows 窗体组件(如 ToolStripItem)不支持设置绑定。
设置序列化
LocalFileSettingsProvider 必须将设置保存到磁盘时,它将执行以下操作:
使用反射检查在 ApplicationSettingsBase 派生类上定义的所有属性,查找应用于 ApplicationScopedSettingAttribute 或 UserScopedSettingAttribute的属性。
将属性序列化并保存到磁盘。 它首先尝试在类型关联的 TypeConverter上调用 ConvertToString 或 ConvertFromString。 如果未成功,则改用 XML 序列化。
根据设置的属性确定哪些设置进入哪些文件。
如果你实现自己的设置类,可以使用 SettingsSerializeAsAttribute 来标记需通过 SettingsSerializeAs 枚举进行二进制或自定义序列化的设置。 有关在代码中创建自己的设置类的详细信息,请参阅 如何:创建应用程序设置。
设置文件位置
app
.exe.config 和 用户.config 文件的位置因应用程序的安装方式而异。 对于复制到本地计算机上的基于 Windows 窗体的应用程序,app
.exe.config 将驻留在与应用程序主可执行文件的基目录相同的目录中,用户.config 将驻留在由 Application.LocalUserAppDataPath 属性指定的位置。 对于通过 ClickOnce 安装的应用程序,这两个文件将位于 %InstallRoot%\Documents and Settings\ 下的 ClickOnce 数据目录中,用户名\Local Settings。
如果用户启用了漫游配置文件,则这些文件的存储位置略有不同,这允许用户在域中使用其他计算机时定义不同的 Windows 和应用程序设置。 在这种情况下,ClickOnce 应用程序和非 ClickOnce 应用程序的 app
.exe.config 和 用户.config 文件将会存储在 %InstallRoot%\Documents and Settings\用户名\Application Data 下。
有关应用程序设置功能如何与新的部署技术配合使用的详细信息,请参阅 ClickOnce 和应用程序设置。 有关 ClickOnce 数据目录的详细信息,请参阅 访问 ClickOnce 应用程序中的本地和远程数据。
应用程序设置和安全性
应用程序设置被设计为在有限的信任环境下工作,这是通过互联网或内联网托管的 Windows 窗体应用程序的默认环境。 除了部分信任之外,不需要任何特殊权限才能将应用程序设置与默认设置提供程序一起使用。
当 ClickOnce 应用程序中使用应用程序设置时,user
.config 文件存储在 ClickOnce 数据目录中。 应用程序 user
.config 文件的大小不能超过 ClickOnce 设置的数据目录配额。 有关详细信息,请参阅 ClickOnce 和应用程序设置。
自定义设置提供程序
在应用程序设置架构中,应用程序设置包装器类(源自 ApplicationSettingsBase)与相关的设置提供程序或提供程序(源自 SettingsProvider)之间存在松散耦合。 此关联仅由应用于包装类或其单个属性的 SettingsProviderAttribute 定义。 如果未显式指定设置提供程序,则使用默认提供程序 LocalFileSettingsProvider。 因此,此体系结构支持创建和使用自定义设置提供程序。
例如,假设你想要开发和使用 SqlSettingsProvider
,这是一个提供程序,它将将所有设置数据存储在Microsoft SQL Server 数据库中。 派生自 SettingsProvider的类将在其 Initialize
方法中接收此信息,作为 System.Collections.Specialized.NameValueCollection类型的参数。 然后,你将实现 GetPropertyValues 方法来从数据存储中检索设置,并 SetPropertyValues 保存这些设置。 提供程序可以使用提供给 GetPropertyValues 的 SettingsPropertyCollection 来确定属性的名称、类型和范围,以及为该属性定义的任何其他设置属性。
提供程序需要实现一个属性和一个方法,其实现可能并不明显。 ApplicationName 属性是 SettingsProvider的抽象属性;应对其进行编程以返回以下内容:
public override string ApplicationName
{
get
{
return (System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
}
set
{
// Do nothing.
}
}
Public Overrides Property ApplicationName() As String
Get
ApplicationName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name
End Get
Set(ByVal value As String)
' Do nothing.
End Set
End Property
派生类还必须实现一个 Initialize
方法,该方法不采用任何参数,并且不返回任何值。 此方法不是由 SettingsProvider定义的。
最后,在提供程序上实现 IApplicationSettingsProvider,以支持刷新设置、将设置还原为其默认设置,以及将设置从一个应用程序版本升级到另一个应用程序版本。
实现并编译提供程序后,需要指示设置类使用此提供程序而不是默认值。 可通过 SettingsProviderAttribute完成此操作。 如果应用于整个设置类,则提供程序用于类定义的每个设置;如果应用于单个设置,则应用程序设置体系结构仅使用该提供程序进行这些设置,并为其余设置使用 LocalFileSettingsProvider。 下面的代码示例演示如何指示设置类使用自定义提供程序。
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace ApplicationSettingsArchitectureCS
{
[SettingsProvider("SqlSettingsProvider")]
class CustomSettings : ApplicationSettingsBase
{
// Implementation goes here.
}
}
Imports System.Configuration
<SettingsProvider("SqlSettingsProvider")> _
Public Class CustomSettings
Inherits ApplicationSettingsBase
' Implementation goes here.
End Class
提供程序可以同时从多个线程调用,但它将始终写入同一存储位置;因此,应用程序设置体系结构只会实例化提供程序类的单个实例。
重要
应确保提供程序是线程安全的,并且每次只允许一个线程写入配置文件。
提供程序不需要支持在 System.Configuration 命名空间中定义的所有设置属性,但至少必须支持 ApplicationScopedSettingAttribute 和 UserScopedSettingAttribute,并且还应支持 DefaultSettingValueAttribute。 对于它不支持的属性,提供商应仅在不通知的情况下失败;它不应引发异常。 但是,如果设置类使用属性的无效组合(例如将 ApplicationScopedSettingAttribute 和 UserScopedSettingAttribute 应用于同一设置),则提供程序应引发异常并停止操作。