应用程序设置体系结构
本主题介绍应用程序设置体系结构的工作原理,并探讨了体系结构的高级功能,如分组设置和设置键。
应用程序设置体系结构支持定义应用程序或用户范围的强类型设置,并支持保留应用程序会话间的设置。 该体系结构提供一个默认的持久性引擎,用于将设置保存到本地文件系统以及从本地文件系统加载设置。 该体系结构还定义了用于提供自定义持久性引擎的接口。
在应用程序中托管自定义组件时,利用提供的接口可使这些自定义组件保留其自己的设置。 通过使用设置键,组件能够保持分隔组件多个实例的设置。
定义设置
应用程序设置体系结构用于 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 始终可读/写。 有关详细信息,请参阅存储用户范围设置的位置。
所有这 3 种配置文件都以 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 和 user.config 文件的位置因应用程序的安装方式而异。 对于复制到本地计算机上的基于 Windows 窗体的应用程序,app
.exe.config 驻留在与该应用程序主可执行文件所在基目录相同的目录中,而 user.config 驻留在由 Application.LocalUserAppDataPath 属性指定的位置中。 对于通过 ClickOnce 安装的应用程序,这两个文件都驻留在 %InstallRoot%\Documents and Settings\username\Local Settings 下的 ClickOnce 数据目录中。
如果用户启用了漫游配置文件,则这些文件的存储位置稍有不同,漫游配置文件可使用户在域内使用其他计算机时定义不同的 Windows 和应用程序设置。 在这种情况下,ClickOnce 应用程序和非 ClickOnce 应用程序的 app
.exe.config 和 user.config 文件均存储在 %InstallRoot%\Documents and Settings\username\Application Data 下。
若要深入了解应用程序设置功能如何与新部署技术协同使用,请参阅 ClickOnce 和应用程序设置。 有关 ClickOnce 数据目录的详细信息,请参阅在 ClickOnce 应用程序中访问本地数据和远程数据。
应用程序设置和安全
应用程序设置设计为在部分信任的受限环境中运行,该环境是通过 Internet 或 Intranet 托管的 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 应用于同一设置,则提供程序应引发异常并终止操作。