c# - 読み込み - wpf 設定 ファイル




Windowsフォームアプリケーションにアプリケーション設定を保存するためのベストプラクティス (9)

私が達成したいのは、非常にシンプルです。情報を読み取るためのパスを使用するWindows Forms(.NET 3.5)アプリケーションがあります。 このパスは、ユーザーがオプションフォームを使用して変更できます。

今度は、後で使用するためにパス値をファイルに保存します。 これは、このファイルに保存される多くの設定の1つになります。 このファイルはアプリケーションフォルダに直接置かれます。

3つのオプションが利用可能であると私は理解しています

  • ConfigurationSettingsファイル(appname.exe.config)
  • レジストリ
  • カスタムXMLファイル

私は、.NET設定ファイルが値を保存するために予期されていないことを読んでいます。 レジストリについては、できるだけ遠くに行きたいと思っています。

つまり、カスタムXMLファイルを使用して構成設定を保存する必要がありますか? もしそうなら、私はそのコード例(C#)を見たいと思います。

私はこのテーマについて他の議論を見てきましたが、それでも私には分かりません。


registry / configurationSettings / XMLの引数はまだ非常にアクティブなようです。 技術が進歩するにつれて私はそれらをすべて使いましたが、私のお気に入りはThreedのシステムIsolated Storageを組み合わせたものです。

次のサンプルでは、​​プロパティという名前のオブジェクトを独立したストレージに格納することができます。 といった:

AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");

プロパティは以下を使用して復元できます。

AppSettings.Load(myobject, "myFile.jsn");

ベストプラクティスを示唆するものではなく、単なるサンプルです。

internal static class AppSettings
{
    internal static void Save(object src, string targ, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = src.GetType();

        string[] paramList = targ.Split(new char[] { ',' });
        foreach (string paramName in paramList)
            items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null));

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify.
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write((new JavaScriptSerializer()).Serialize(items));
            }

        }
        catch (Exception) { }   // If fails - just don't use preferences
    }

    internal static void Load(object tar, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = tar.GetType();

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage))
            using (StreamReader reader = new StreamReader(stream))
            {
                items = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(reader.ReadToEnd());
            }
        }
        catch (Exception) { return; }   // If fails - just don't use preferences.

        foreach (KeyValuePair<string, object> obj in items)
        {
            try
            {
                tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null);
            }
            catch (Exception) { }
        }
    }
}

「設定XMLファイルを使用して設定を保存する必要がありますか? いいえ、必須ではありません。 このような操作にはSharpConfigを使用します。

例えば、設定ファイルがそのようなものである場合

[General]
# a comment
SomeString = Hello World!
SomeInteger = 10 # an inline comment

このような値を取得できます

var config = Configuration.LoadFromFile("sample.cfg");
var section = config["General"];

string someString = section["SomeString"].StringValue;
int someInteger = section["SomeInteger"].IntValue;

それは.Net 2.0以上と互換性があります。 設定ファイルはオンザフライで作成でき、後で保存することができます。 ソース: http://sharpconfig.net/ ://sharpconfig.net/ Github: https://github.com/cemdervis/SharpConfig : https://github.com/cemdervis/SharpConfig

私はそれが助けて欲しい


Visual Studioを使用している場合、持続可能な設定を取得するのは簡単です。 ソリューションエクスプローラでプロジェクトを右クリックし、[プロパティ]を選択します。 [設定]タブを選択し、設定が存在しない場合はハイパーリンクをクリックします。 [設定]タブを使用してアプリケーション設定を作成します。 Visual Studioは、 ApplicationSettingsBaseから継承したシングルトンクラスのSettingsを含むSettings.settingsおよびSettings.Designer.settingsファイルを作成します。 コードからこのクラスにアクセスして、アプリケーション設定を読み書きできます。

Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file

この手法は、コンソール、Windowsフォーム、および他のプロジェクトタイプの両方に適用されます。

設定のスコーププロパティを設定する必要があることに注意してください。 アプリケーションスコープを選択すると、Settings.Default。<your property>は読み取り専用になります。


レジストリは無事です。 アプリケーションを使用するユーザーにレジストリに書き込むための十分な権限があるかどうかはわかりません。

app.configファイルを使用すると、アプリケーションレベルの設定(アプリケーションを使用する各ユーザーと同じ)を保存できます。

私はユーザー固有の設定をXMLファイルに保存し、 Isolated StorageまたはSpecialFolder.ApplicationDataディレクトリに保存します。

それに続いて、.NET 2.0のように、値をapp.configファイルに保存することも可能です。


場合によっては、従来のweb.configまたはapp.configファイルに保存されている設定を取り除きたいことがあります。 設定エントリの展開やデータの分離設計に対して、より細かく制御する必要があります。 または、実行時に新しいエントリを追加できるようにする必要があります。

私は2つの良いオプションを想像することができます:

  • 強く型付けされたバージョン
  • オブジェクト指向バージョン。

強く型付けされたバージョンの利点は、強く型付けされた設定の名前と値です。 名前やデータタイプを混在させる危険はありません。 欠点は、より多くの設定をコード化しなければならず、実行時に追加することができないことです。

オブジェクト指向バージョンでは、実行時に新しい設定を追加できる利点があります。 しかし、強く型付けされた名前と値はありません。 文字列識別子には注意が必要です。 以前に値を取得したときに保存されたデータ型を知っていなければなりません。

ここでは、完全に機能する実装のコードを見つけることができます。


実行可能ファイルと同じディレクトリにあるファイルに保存する予定の場合は、 JSON形式を使用する優れたソリューションを次に示しJSON

using System;
using System.IO;
using System.Web.Script.Serialization;

namespace MiscConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            MySettings settings = MySettings.Load();
            Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
            Console.WriteLine("Incrementing 'myInteger'...");
            settings.myInteger++;
            Console.WriteLine("Saving settings...");
            settings.Save();
            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        class MySettings : AppSettings<MySettings>
        {
            public string myString = "Hello World";
            public int myInteger = 1;
        }
    }

    public class AppSettings<T> where T : new()
    {
        private const string DEFAULT_FILENAME = "settings.json";

        public void Save(string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
        }

        public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
        }

        public static T Load(string fileName = DEFAULT_FILENAME)
        {
            T t = new T();
            if(File.Exists(fileName))
                t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
            return t;
        }
    }
}


私はこのために構築した図書館を共有したかったのです。 小さなライブラリですが、.settingsファイルを大きく改善しました(IMHO)。

ライブラリはJot(GitHub)と呼ばれ、ここで私が書いた古いThe Code Projectの記事があります。

ウィンドウのサイズと場所を追跡する方法は次のとおりです。

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

.settingsファイルと比較した場合の利点:コードはかなり少なく、それぞれのプロパティについて一だけ言及する必要があるため、エラーが発生しにくいです。

設定ファイルでは、プロパティを明示的に作成するときに1回、前後に値をコピーするコードで4回追加するときに、各プロパティを5回言及する必要があります。

ストレージ、シリアル化などは完全に構成可能です。 コントロールの反転を使用するときは、トラッキングするすべてのオブジェクトに自動的にトラッキングを適用し、プロパティを永続化するために行う必要があるすべてのオブジェクトに[Trackable]属性を適用することができます。

私は図書館が一流であると思うので、これをすべて書いています。私はそれを普及したいと思います:)


public static class SettingsExtensions
{
    public static bool TryGetValue<T>(this Settings settings, string key, out T value)
    {
        if (settings.Properties[key] != null)
        {
            value = (T) settings[key];
            return true;
        }

        value = default(T);
        return false;
    }

    public static bool ContainsKey(this Settings settings, string key)
    {
        return settings.Properties[key] != null;
    }

    public static void SetValue<T>(this Settings settings, string key, T value)
    {
        if (settings.Properties[key] == null)
        {
            var p = new SettingsProperty(key)
            {
                PropertyType = typeof(T),
                Provider = settings.Providers["LocalFileSettingsProvider"],
                SerializeAs = SettingsSerializeAs.Xml
            };
            p.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
            var v = new SettingsPropertyValue(p);
            settings.Properties.Add(p);
            settings.Reload();
        }
        settings[key] = value;
        settings.Save();
    }
}




application-settings