应用程序设置体系结构

本主题介绍应用程序设置体系结构的工作原理,并探索体系结构的高级功能,例如分组设置和设置键。

应用程序设置架构支持用应用程序或用户范围定义强类型的设置,并在应用程序会话之间保存设置。 该体系结构提供默认持久性引擎,用于保存设置并将其从本地文件系统加载。 该体系结构还定义了用于提供自定义持久性引擎的接口。

提供了允许自定义组件在应用程序中托管时保留其自己的设置的接口。 通过使用设置键,组件可以保留组件多个实例的设置分开。

定义设置

应用程序设置体系结构在 ASP.NET 和 Windows 窗体中使用,并且包含跨两个环境共享的多个基类。 最重要的是 SettingsBase,它通过集合提供对设置的访问,并提供用于加载和保存设置的低级别方法。 每个环境实现其派生自 SettingsBase 的类,为该环境提供其他设置功能。 在基于 Windows 窗体的应用程序中,必须在派生自该类的 ApplicationSettingsBase 类上定义所有应用程序设置,该类将以下功能添加到基类:

  • 更高级别的加载和保存操作

  • 支持用户特定范围的设置

  • 将用户的设置还原为预定义的默认值

  • 从以前的应用程序版本升级设置

  • 在更改设置之前或保存设置之前验证设置

可以使用命名空间中 System.Configuration 定义的多个属性来描述这些设置;这些属性在 应用程序设置属性中介绍。 定义设置时,必须使用或ApplicationScopedSettingAttributeUserScopedSettingAttribute应用此设置,该设置是应用于整个应用程序还是仅适用于当前用户。

下面的代码示例使用单个设置 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 ,它将执行以下作:

  1. 使用反射来检查在您的ApplicationSettingsBase派生类上定义的所有属性,查找那些使用ApplicationScopedSettingAttributeUserScopedSettingAttribute应用的属性。

  2. 将属性序列化并保存到磁盘。 它首先尝试调用类型的关联 TypeConverter 中的 ConvertToStringConvertFromString。 如果未成功,则改用 XML 序列化。

  3. 根据设置的属性确定哪些设置放入哪些文件中。

如果实现自己的设置类,则可以使用SettingsSerializeAsAttribute来标记需要使用SettingsSerializeAs枚举进行二进制或自定义序列化的设置。 有关在代码中创建自己的设置类的详细信息,请参阅 如何:创建应用程序设置

设置文件位置

.exe.config 和用户.config 文件的位置app因应用程序的安装方式而异。 对于复制到本地计算机上的基于 Windows 窗体的应用程序, app.exe.config 将驻留在与应用程序主可执行文件的基目录相同的目录中, 用户.config 将驻留在属性指定的 Application.LocalUserAppDataPath 位置。 对于通过 ClickOnce 安装的应用程序,这两个文件将驻留在 %InstallRoot%\Documents and Settings\username\Local Settings 下的 ClickOnce 数据目录中。

如果用户启用了漫游配置文件,则这些文件的存储位置略有不同,这允许用户在域中使用其他计算机时定义不同的 Windows 和应用程序设置。 在这种情况下,ClickOnce 应用程序和非 ClickOnce 应用程序都将在其 app.exe.config 和 用户.config 文件存储在 %InstallRoot%\Documents and Settings\username\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 保存这些设置。 提供程序可以使用 SettingsPropertyCollection 所提供的属性来确定 GetPropertyValues 属性的名称、类型和范围,以及为该属性定义的任何其他设置属性。

提供程序需要实现一个属性和一个方法,其实现可能并不明显。 该 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定义的所有设置属性,但至少必须支持ApplicationScopedSettingAttributeUserScopedSettingAttribute,同时也应该支持DefaultSettingValueAttribute。 对于它不支持的属性,提供商应仅在不通知的情况下失败;它不应引发异常。 但是,如果设置类使用属性的无效组合(例如应用 ApplicationScopedSettingAttributeUserScopedSettingAttribute 应用于同一设置),则提供程序应引发异常并停止作。

另请参阅