Глобальные редактируемые параметры конфигурации в C#.NET ?

#c#

#c#

Вопрос:

Я хочу лучшее из обоих миров: я хочу иметь возможность сохранять изменения во время выполнения, как это делают настройки пользовательского приложения, и я также хочу, чтобы эти настройки были глобальными. Есть ли какой-нибудь способ выполнить это с помощью файлов настроек app.config? Должен ли я искать какой-либо другой способ сохранения глобальных, редактируемых во время выполнения настроек для моего приложения?

Ответ №1:

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

 ConfigurationManager.RefreshSection("appSettings")
  

когда вы хотите перезагрузить свои настройки

Ответ №2:

Кроме того, метод OpenMappedExeConfiguration() в ConfigurationManager позволяет динамически загружать файл конфигурации по вашему выбору (при условии, что он соответствует конфигурационной схеме .NET xml) и загружать из него параметры конфигурации вашего приложения, так что вы можете вносить изменения в файл, как указал @lomax, и иметь общий файл, который вы можете загружать из всех ваших приложений, используя этот же метод.

Вот некоторая информация о OpenMappedExeConfiguration

Ответ №3:

Хорошо, вот как я это решил:

Я создал действительно базовые ConfigurationSection , ConfigurationElement и ConfigurationElementCollection реализации:

 public class CoreConfigurationSection : ConfigurationSection
{
    [ConfigurationProperty("settings", IsDefaultCollection = true)]
    [ConfigurationCollection(typeof(CoreSettingCollection), AddItemName = "setting")]
    public CoreSettingCollection Settings
    {
        get
        {
            return (CoreSettingCollection)base["settings"];
        }
    }
}

public class CoreSetting : ConfigurationElement
{
    public CoreSetting() { }

    public CoreSetting(string name, string value)
    {
        Name = name;
        Value = value;
    }

    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
    public string Name
    {
        get { return (string)this["name"]; }
        set { this["name"] = value; }
    }

    [ConfigurationProperty("value", DefaultValue = null, IsRequired = true, IsKey = false)]
    public string Value
    {
        get { return (string)this["value"]; }
        set { this["value"] = value; }
    }
}

public class CoreSettingCollection : ConfigurationElementCollection
{
    public new string this[string name]
    {
        get { return BaseGet(name) == null ? string.Empty : ((CoreSetting)BaseGet(name)).Value; }
        set { Remove(name); Add(name, value); }
    }

    public void Add(string name, string value)
    {
        if (!string.IsNullOrEmpty(value))
            BaseAdd(new CoreSetting(name, value));
    }

    public void Remove(string name)
    {
        if (BaseGet(name) != null)
            BaseRemove(name);
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new CoreSetting();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((CoreSetting)element).Name;
    }
}
  

А затем класс для управления файлом конфигурации:

 public static class Settings
{
    private static string _root { get { return "core"; } }

    private static Configuration Load()
    {
        string filename = Path.Combine(Core.BaseDirectory, "core.config");

        var mapping = new ExeConfigurationFileMap {ExeConfigFilename = filename};
        var config = ConfigurationManager.OpenMappedExeConfiguration(mapping, ConfigurationUserLevel.None);

        var section = (CoreConfigurationSection)config.GetSection(_root);

        if (section == null)
        {
            Console.Write("Core: Building core.config...");

            section = new CoreConfigurationSection();
            config.Sections.Add(_root, section);
            Defaults(section);
            config.Save(ConfigurationSaveMode.Modified);

            Console.WriteLine("done");
        }

        return config;
    }

    private static void Defaults(CoreConfigurationSection section)
    {
        section.Settings["Production"] = "false";
        section.Settings["Debug"] = "false";
        section.Settings["EventBot"] = "true";
        section.Settings["WebAccounting"] = "true";
        section.Settings["AllowPlayers"] = "true";
    }

    #region Accessors

    public static string Get(string setting)
    {
        var config = Load();
        var section = (CoreConfigurationSection)config.GetSection(_root);

        return section.Settings[setting];
    }

    public static bool GetBoolean(string setting)
    {
        var config = Load();
        var section = (CoreConfigurationSection)config.GetSection(_root);

        return section.Settings[setting].ToLower() == "true";
    }

    public static void Set(string setting,string value)
    {
        var config = Load();
        var section = (CoreConfigurationSection)config.GetSection(_root);

        if (value == null)
            section.Settings.Remove(setting);

        section.Settings[setting] = value;
        config.Save(ConfigurationSaveMode.Modified);
    }

    public static void SetBoolean(string setting, bool value)
    {
        var config = Load();
        var section = (CoreConfigurationSection)config.GetSection(_root);

        section.Settings[setting] = value.ToString();
        config.Save(ConfigurationSaveMode.Modified);
    }

    #endregion

    #region Named settings

    public static bool Production
    {
        get { return GetBoolean("Production"); }
        set { SetBoolean("Production", value); }
    }

    public static bool Debug
    {
        get { return GetBoolean("Debug"); }
        set { SetBoolean("Debug", value); }
    }

    public static bool EventBot
    {
        get { return GetBoolean("EventBot"); }
        set { SetBoolean("EventBot", value); }
    }

    public static bool WebAccounting
    {
        get { return GetBoolean("WebAccounting"); }
        set { SetBoolean("WebAccounting", value); }
    }

    public static bool AllowPlayers
    {
        get { return GetBoolean("AllowPlayers"); }
        set { SetBoolean("AllowPlayers", value); }
    }

    #endregion
}
  

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

Файл core.config создается во время выполнения, если он не существует, это проверяется всякий раз, когда вы пытаетесь загрузить или сохранить настройку с некоторыми значениями по умолчанию просто для «начала»… (впрочем, вы можете пропустить эту «инициализацию».

Файл core.config выглядит следующим образом

 <?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="core" type="Server.CoreConfigurationSection, ServerCore, Version=2.1.4146.38077, Culture=neutral, PublicKeyToken=null" />
    </configSections>
    <core>
        <settings>
            <setting name="Production" value="false" />
            <setting name="Debug" value="false" />
            <setting name="EventBot" value="true" />
            <setting name="WebAccounting" value="true" />
            <setting name="AllowPlayers" value="true" />
        </settings>
    </core>
</configuration>