пример - c# xml config file




Лучшая практика сохранения настроек приложения в приложении Windows Forms (9)

«Означает ли это, что я должен использовать собственный файл 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/ Github: https://github.com/cemdervis/SharpConfig

Я надеюсь, что это помогает.

То, что я хочу достичь, очень просто: у меня есть приложение Windows Forms (.NET 3.5), которое использует путь для чтения информации. Этот путь может быть изменен пользователем, используя форму, которую я предоставляю.

Теперь я хочу сохранить значение пути в файл для последующего использования. Это будет одна из многих настроек, сохраненных в этом файле. Этот файл будет находиться непосредственно в папке приложения.

Я понимаю, что доступны три варианта:

  • Файл ConfigurationSettings (appname.exe.config)
  • реестр
  • Пользовательский XML-файл

Я читал, что конфигурационный файл .NET не предусмотрен для сохранения значений. Что касается реестра, я хотел бы получить как можно дальше от него.

Означает ли это, что я должен использовать собственный файл XML для сохранения настроек конфигурации? Если это так, я хотел бы увидеть пример кода (C #).

Я видел другие дискуссии по этому вопросу, но мне все еще не ясно.


Аргумент registry / configurationSettings / XML по-прежнему кажется очень активным. Я использовал их все, так как технология прогрессировала, но мой фаворит основан на системе Тридда в сочетании с изолированным хранилищем .

Следующий пример позволяет хранить объекты с именем properties в файле в изолированном хранилище. Такие как:

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) { }
        }
    }
}

Если вы планируете сохранить файл в том же каталоге, что и ваш исполняемый файл, вот хорошее решение, которое использует формат 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;
        }
    }
}

Иногда вы хотите избавиться от этих настроек, хранящихся в традиционном файле web.config или app.config. Вы хотите более мелкомасштабный контроль над развертыванием ваших записей настроек и разделенным дизайном данных. Или необходимо включить добавление новых записей во время выполнения.

Я могу представить два хороших варианта:

  • Строго типизированная версия и
  • Объектно-ориентированная версия.

Преимущество строго типизированной версии - это строго типизированные имена и значения параметров. Нет риска смешения имен или типов данных. Недостатком является то, что больше настроек должно быть закодировано, не может быть добавлено во время выполнения.

Преимуществом объектно-ориентированной версии является то, что во время выполнения можно добавлять новые настройки. Но у вас нет строго типизированных имен и значений. Будьте осторожны с строковыми идентификаторами. Должен знать тип данных, сохраненный ранее при получении значения.

Вы можете найти код как полнофункциональных реализаций HERE .



Насколько я могу судить, .NET поддерживает постоянные настройки с помощью встроенного средства настройки приложений:

Функция «Параметры приложения» в Windows Forms упрощает создание, хранение и обслуживание пользовательских приложений и пользовательских настроек на клиентском компьютере. С настройками приложения Windows Forms вы можете хранить не только данные приложения, такие как строки подключения к базе данных, но и данные, специфичные для пользователя, такие как настройки пользовательского приложения. Используя Visual Studio или настраиваемый управляемый код, вы можете создавать новые настройки, читать их и записывать на диск, привязывать их к свойствам в своих формах и проверять данные настроек до загрузки и сохранения. - http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx


Реестр не работает. Вы не уверены, имеет ли пользователь, который использует ваше приложение, достаточные права на запись в реестр.

Файл app.config можно использовать для сохранения настроек уровня приложения (которые одинаковы для каждого пользователя, использующего ваше приложение).

Я бы сохранил пользовательские настройки в файле XML, который будет сохранен в изолированном хранилище или в каталоге SpecialFolder.ApplicationData .

Рядом с этим, как и с .NET 2.0, можно сохранить значения обратно в файл app.config .


Я хотел поделиться библиотекой, которую я создал для этого. Это небольшая библиотека, но большое улучшение (IMHO) над файлами .settings.

Библиотека называется Jot (GitHub) , вот старая статья 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: значительно меньше кода, и он намного менее подвержен ошибкам, так как вам нужно только указать каждое свойство один раз .

С помощью файлов настроек вам нужно указать каждое свойство пять раз: один раз, когда вы явно создаете свойство и еще четыре раза в коде, который копирует значения взад и вперед.

Хранение, сериализация и т. Д. Полностью настраиваются. При использовании инверсии элемента управления вы можете подключить его так, чтобы он автоматически отслеживал все объекты, которые он разрешает, чтобы все, что вам нужно сделать, чтобы сохранить свойство, - это пощелкать на нем атрибут [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