AbstractSettings.cs

設定の書き込み・読み込みを行うための抽象クラス。
Visual Studio標準の設定保存・読み込みクラスが、あまりにも使いにくいので作成。

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Win32;



/// 
/// アプリケーションの設定情報を操作する抽象クラス。
/// 
/// 
/// 設定の書き出し、読み込み、削除を行う。
/// 操作対象は、継承先で定義されたpublicインスタンスフィールド。
/// 使用可能な形式を次に示す。
/// 
/// 
///     INI:
///     INIファイル(*.ini)を使用する。対象はプリミティブ型のみ。
/// 
/// 
///     XML:
///     XMLファイル(*.xml)を使用する。対象はシリアライズ可能なオブジェクト。
/// 
/// 
///     レジストリ:
///     レジストリを使用する。対象はプリミティブ型のみ。
/// 
/// 
/// 
/// 次の規則に従って初期値が設定される。
/// 
/// 
///     ディレクトリパス:
///     呼び出し元アセンブラディレクトリ。(変更可能)
/// 
/// 
///     ファイル名/キー:
///     呼び出し元アセンブラ名 + 拡張子。(変更可能)
/// 
/// 
///     セクション名/サブキー:
///     クラス名。
/// 
/// 
///     設定名/データ名:
///     変数名。
/// 
/// 
/// 
public abstract class AbstractSettings
{

    #region 設定情報

    /// セクション名。
    protected readonly string SECTION_NAME;
    /// 設定情報を定義(継承先のpublicインスタンスプロパティを設定情報と定義する)。
    protected readonly PropertyInfo[] SETTINGS_PROPERTIES;

    /// 呼び出し元のアセンブリパス。
    protected readonly string EXEC_PATH;
    /// 設定ファイルの絶対ディレクトリパス。
    protected string DIR_PATH;
    /// 設定ファイルの拡張子を除くファイル名。
    protected string FILE_NAME;

    /// 
    /// 新しいインスタンスを初期化する。
    /// 
    public AbstractSettings()
    {
        // 設定情報
        SECTION_NAME = this.GetType().Name;
        SETTINGS_PROPERTIES = this.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly);
        
        // パス情報
        EXEC_PATH = Assembly.GetExecutingAssembly().Location;
        DIR_PATH  = Path.GetDirectoryName(EXEC_PATH);
        FILE_NAME = Path.GetFileName(EXEC_PATH);
    }

    /// 
    /// 設定ファイルのディレクトリパスを変更する。
    /// 
    /// ディレクトリパス(絶対パス/相対パス)。public void SetDirPath(string dir)
    {
        // 指定が無効の場合は何もしない。
        if (dir == null || dir == "") return;

        if (Path.IsPathRooted(dir))
            DIR_PATH = dir; // 絶対パス
        else
            DIR_PATH = Path.Combine(DIR_PATH, dir); // 相対パス
    }

    /// 
    /// 設定ファイルのファイル名を変更する。
    /// 
    /// 拡張子を除くファイル名。public void SetFileName(string file)
    {
        // 指定が無効の場合は何もしない。
        if (file == null || file == "") return;

        FILE_NAME = file;
    }

    #endregion



    #region INIファイル

    /// 
    /// INIファイルのパスを取得する。
    /// 
    public string IniPath
    {
        get
        {
            return Path.Combine(DIR_PATH, FILE_NAME + ".ini");
        }
    }

    /// 
    /// INIファイルから設定を読み込む。
    /// 
    public void ReadIni()
    {
        string path = IniPath;
        if (!File.Exists(path)) return;

        foreach (PropertyInfo info in SETTINGS_PROPERTIES)
        {
            // プリミティブ型またはString型以外の値は無視
            if (!info.PropertyType.IsPrimitive &&
                info.PropertyType != typeof(string))
                continue;
            
            // INIファイルの読み込み
            StringBuilder value = new StringBuilder(256);
            GetPrivateProfileString(
                SECTION_NAME, info.Name, "", value, (uint)value.Capacity, path);
            if (value.Length > 0)
                info.SetValue(this, Convert.ChangeType(value.ToString(), info.PropertyType, null), null);
        }
    }

    /// 
    /// INIファイルに設定を書き込む。
    /// 
    public void WriteIni()
    {
        string path = IniPath;

        foreach (PropertyInfo info in SETTINGS_PROPERTIES)
        {
            // プリミティブ型またはString型意外の値は無視
            if (!info.PropertyType.IsPrimitive &&
                info.PropertyType != typeof(string))
                continue;

            // INIファイルの書き込み
            string value = info.GetValue(this, null).ToString();
            if (info.PropertyType == typeof(string))
                value = """ + value + """;
            WritePrivateProfileString(
                SECTION_NAME, info.Name, value, path);
        }
    }

    /// 
    /// INIファイルを削除する。
    /// 
    public void DeleteIni()
    {
        string path = IniPath;
        File.Delete(path);
    }

    /// 
    /// INIファイル読み込み関数宣言。(Win32API)
    /// 
    /// セクション名。/// キー名。/// デフォルト値。/// 値。/// 値のサイズ。/// INIファイルパス。/// 成功の場合は取得した文字数。
    [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileString")]
    protected static extern uint GetPrivateProfileString(
            string lpApplicationName,
            string lpEntryName,
            string lpDefault,
            StringBuilder lpReturnedString,
            uint nSize,
            string lpFileName);

    /// 
    /// INIファイル書き込み関数宣言。(Win32API)
    /// 
    /// セクション名。/// キー名。/// 値。/// INIファイルパス。/// 成功の場合は0以外。
    [DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileString")]
    protected static extern uint WritePrivateProfileString(
            string lpApplicationName,
            string lpEntryName,
            string lpEntryString,
            string lpFileName);

    #endregion



    #region XMLファイル

    /// 
    /// XMLファイルのパスを取得する。
    /// 
    public string XmlPath
    {
        get
        {
            return Path.Combine(DIR_PATH, FILE_NAME + ".xml");
        }
    }

    /// 
    /// XMLファイルから設定を読み込む。
    /// 
    public void ReadXml()
    {
        string path = XmlPath;
        if (!File.Exists(path)) return;

        // XMLファイルの読み込み
        XmlSerializer serializer = new XmlSerializer(this.GetType());
        using (FileStream inputStream = new FileStream(path, FileMode.Open))
        {
            Object set = serializer.Deserialize(inputStream);
            foreach (PropertyInfo info in SETTINGS_PROPERTIES)
            {
                info.SetValue(this, Convert.ChangeType(info.GetValue(set, null), info.PropertyType, null), null);
            }
        }
    }

    /// 
    /// XMLファイルに設定を書き込む。
    /// 
    public void WriteXml()
    {
        string path = XmlPath;

        // XMLファイルの書き込み
        XmlSerializer serializer = new XmlSerializer(this.GetType());
        using (FileStream outputStream = new FileStream(path, FileMode.Create))
        {
            serializer.Serialize(outputStream, this);
        }
    }

    /// 
    /// XMLファイルを削除する。
    /// 
    public void DeleteXml()
    {
        string path = XmlPath;
        File.Delete(path);
    }

    #endregion



    #region レジストリ

    /// 
    /// レジストリのキーを取得する。
    /// 
    public string RegistryPath
    {
        get
        {
            return "Software" + FILE_NAME + "" + SECTION_NAME;
        }
    }

    /// 
    /// レジストリから設定を読み込む。
    /// 
    public void ReadRegistry()
    {
        string path = RegistryPath;

        using (RegistryKey key = Registry.CurrentUser.OpenSubKey(path, false))
        {
            if (key == null) return;

            foreach (PropertyInfo info in SETTINGS_PROPERTIES)
            {
                // プリミティブ型またはString型以外の値は無視
                if (!info.PropertyType.IsPrimitive &&
                    info.PropertyType != typeof(string))
                    continue;

                // レジストリの読み込み
                object value = key.GetValue(info.Name);
                if (value != null)
                    info.SetValue(this, Convert.ChangeType(value, info.PropertyType, null), null);
            }
        }
    }

    /// 
    /// レジストリに設定を書き込む。
    /// 
    public void WriteRegistry()
    {
        string path = RegistryPath;

        using (RegistryKey key = Registry.CurrentUser.CreateSubKey(path))
        {
            foreach (PropertyInfo info in SETTINGS_PROPERTIES)
            {
                // プリミティブ型またはString型意外の値は無視
                if (!info.PropertyType.IsPrimitive &&
                    info.PropertyType != typeof(string))
                    continue;

                // レジストリの書き込み
                string value = info.GetValue(this, null).ToString();
                key.SetValue(info.Name, info.GetValue(this, null));
            }
        }
    }
    
    /// 
    /// レジストリを削除する。
    /// 
    public void DeleteRegistry(string path)
    {
        string paht = RegistryPath;
        Registry.CurrentUser.DeleteSubKeyTree(path);
    }

    #endregion

}