C#.NET 中的全局可编辑配置设置

本文关键字:编辑 配置 设置 全局 NET | 更新日期: 2023-09-27 17:55:20

我想要两全其美:我希望能够在运行时保留更改,就像用户范围的应用程序设置一样,并且我还希望这些设置是全局的。有没有办法通过app.config设置文件来实现这一点?我是否应该考虑其他方法来为我的应用程序保留全局的运行时可编辑设置?

C#.NET 中的全局可编辑配置设置

.Net 中用于处理配置文件中的应用程序设置的内置配置管理器是只读的,因此从技术上讲,您无法使用内置库执行此操作,但是,配置文件只是 XML,因此没有理由不能使用标准 xml 方法更新配置文件,然后调用

ConfigurationManager.RefreshSection("appSettings")

当您想要重新加载设置时

好的,这就是我解决它的方式:

我创建了非常基本的ConfigurationSectionConfigurationElementConfigurationElementCollection实现:

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 文件在运行时创建(如果不存在),每当您尝试加载或保存设置时都会对此进行验证,使用一些默认值只是为了"入门"......(不过,您可以跳过该"初始化"。

核心.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>

此外,ConfigurationManager 的 OpenMappedExeConfiguration() 方法允许您动态加载您选择的配置文件(假设它遵循 .NET xml 配置架构),并让您的应用程序从中加载配置选项,因此您可以按照@lomax指示修改文件,拥有一个可以从所有应用程序加载的通用文件, 使用相同的方法。

以下是有关OpenMappedExeConfiguration的一些信息