アプリケーション設定アーキテクチャ

このトピックでは、アプリケーション設定アーキテクチャのしくみについて説明します。また、グループ化された設定や設定キーなど、アーキテクチャの高度な機能についても説明します。

アプリケーション設定アーキテクチャでは、アプリケーション スコープまたはユーザー スコープで厳密に型指定された設定の定義と、アプリケーション セッション間での設定の永続化をサポートします。 このアーキテクチャは、ローカル ファイル システムに設定を保存し、ローカル ファイル システムから設定を読み込むための既定の永続化エンジンを提供します。 また、カスタム永続化エンジンを指定するためのインターフェイスも定義します。

アプリケーションでカスタム コンポーネントがホストされているときに、そのコンポーネントの独自の設定を永続化できるようにするインターフェイスが提供されます。 設定キーを使用することで、各コンポーネントはそのコンポーネントの複数のインスタンスの設定を区別できます。

設定の定義

アプリケーション設定アーキテクチャは、ASP.NET 内と Windows フォーム内の両方で使用されます。これには、両方の環境で共有される多数の基底クラスが含まれます。 最も重要なのは SettingsBase です。これにより、コレクションを介して設定にアクセスできるようになり、設定を読み込んだり保存したりするための下位のメソッドが提供されます。 各環境では、SettingsBase から派生した独自のクラスを実装して、その環境用の追加の設定機能を提供します。 Windows フォーム ベースのアプリケーションでは、基底クラスに次の機能を追加する ApplicationSettingsBase クラスから派生したクラスですべてのアプリケーション設定を定義する必要があります。

  • 上位レベルの読み込み操作と保存操作

  • ユーザー スコープの設定のサポート

  • ユーザーの設定を定義済みの既定値に戻す機能

  • 以前のバージョンのアプリケーションの設定のアップグレード

  • 設定の変更前または保存前の検証

設定は、System.Configuration 名前空間内で定義されている多数の属性を使用して表すことができます。これらについては、「アプリケーション設定の属性」を参照してください。 設定を定義する場合は、ApplicationScopedSettingAttribute または UserScopedSettingAttribute を使用して適用する必要があります。これは、設定がアプリケーション全体に適用されるか、現在のユーザーにのみ適用されるかを示します。

次のコード例では、BackgroundColor という 1 つの設定を指定してカスタム設定クラスを定義しています。

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 を実装していても、プロパティの変更通知をサポートしていない場合、プロパティが変更されたときに設定ファイルのバインドは更新されません。

ToolStripItem など、一部の Windows フォーム コンポーネントでは設定のバインドをサポートしていません。

設定のシリアル化

LocalFileSettingsProvider で設定をディスクに保存する必要がある場合は、以下のアクションが行われます。

  1. リフレクションを使用して、ApplicationSettingsBase 派生クラスで定義されているすべてのプロパティを調べ、ApplicationScopedSettingAttribute または UserScopedSettingAttribute を指定して適用されているものを見つけます。

  2. プロパティをディスクにシリアル化します。 まず、型の関連付けられている TypeConverterConvertToString または ConvertFromString の呼び出しを試みます。 この呼び出しが失敗すると、代わりに XML シリアル化を使用します。

  3. 設定の属性に基づいて、どの設定がどのファイルに指定されているかを判断します。

独自の設定クラスを実装している場合は、SettingsSerializeAsAttributeSettingsSerializeAs 列挙型を使用して、設定にバイナリまたはカスタム シリアル化のマークを付けることができます。 コードで独自の設定クラスを作成する方法の詳細については、「方法 : アプリケーション設定を作成する」を参照してください。

設定ファイルの場所

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 アプリケーションにおけるローカル データおよびリモート データへのアクセス」を参照してください。

アプリケーション設定とセキュリティ

アプリケーション設定は部分信頼で機能するように設計されています。部分信頼は、インターネットまたはイントラネット上でホストされる Windows フォーム アプリケーションの既定の制限された環境です。 既定の設定プロバイダーでアプリケーション設定を使用する場合、部分信頼以外の特別なアクセス許可は不要です。

アプリケーション設定が ClickOnce アプリケーション内で使用されている場合、user.config ファイルは ClickOnce データ ディレクトリに格納されます。 アプリケーションの user.config ファイルのサイズは、ClickOnce で設定されたデータ ディレクトリ クォータを超えることはできません。 詳細については、「ClickOnce とアプリケーション設定」を参照してください。

カスタム設定プロバイダー

アプリケーション設定アーキテクチャでは、ApplicationSettingsBase から派生したアプリケーション設定ラッパー クラスと、SettingsProvider から派生した関連する設定プロバイダーの間に疎結合があります。 この関連付けは、ラッパー クラスまたはその個々のプロパティに適用される SettingsProviderAttribute でのみ定義されます。 設定プロバイダーが明示的に指定されていない場合は、既定のプロバイダーである LocalFileSettingsProvider が使用されます。 そのため、このアーキテクチャではカスタム設定プロバイダーの作成と使用がサポートされています。

たとえば、すべての設定データを Microsoft SQL Server データベースに格納するプロバイダーである SqlSettingsProvider を開発して使用するとします。 SettingsProvider の派生クラスでは、Initialize メソッドで System.Collections.Specialized.NameValueCollection 型のパラメーターとしてこの情報を取得します。 その後、データ ストアから設定を取得する GetPropertyValues メソッドと、それらの設定を保存する SetPropertyValues を実装します。 ご利用のプロバイダーでは、GetPropertyValues に指定された SettingsPropertyCollection を使用して、プロパティの名前、型、スコープや、そのプロパティ用に定義されたその他の設定属性を特定できます。

カスタム プロバイダーでは、1 つのプロパティと 1 つのメソッドを実装する必要がありますが、この実装はわかりにくいことがあります。 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

プロバイダーを複数のスレッドから同時に呼び出すことができますが、プロバイダーは常に同じ格納場所に書き込みを行います。したがって、アプリケーション設定アーキテクチャによってインスタンス化されるカスタム プロバイダー クラスのインスタンスは 1 つに限られます。

重要

カスタム プロバイダーがスレッドセーフであり、構成ファイルへの書き込みを実行できるスレッドが一度に 1 つだけであることを確認する必要があります。

ご利用のプロバイダーで、System.Configuration 名前空間で定義されているすべての設定属性をサポートする必要はありませんが、少なくとも ApplicationScopedSettingAttributeUserScopedSettingAttribute をサポートする必要があります。また、DefaultSettingValueAttribute もサポートする必要があります。 サポートされていない属性がある場合、カスタム プロバイダーは通知なしに失敗します。例外をスローする必要はありません。 しかし、設定クラスで属性の無効な組み合わせが使用されている場合 (同じ設定に ApplicationScopedSettingAttributeUserScopedSettingAttribute を適用するなど)、ご利用のプロバイダーで例外をスローし、操作を中止する必要があります。

関連項目