代码之家  ›  专栏  ›  技术社区  ›  Pat

如何动态加载单独的应用程序设置文件并与当前设置合并?

  •  9
  • Pat  · 技术社区  · 15 年前

    有一些问题与 reading settings from a separate config file 以及其他类似的问题,但我的问题是特定于应用程序属性设置(即 <MyApplication.Properties.Settings> -请参见下面的XML文件)以及如何动态加载它们。我试过这个方法 this post ,这涉及刷新主配置文件的整个appsettings部分,但由于我没有替换appsettings部分,因此我的改编引发了异常:

    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
    // Have tried the other ConfigurationUserLevels to no avail
    config.AppSettings.File = myRuntimeConfigFilePath;
    config.Save(ConfigurationSaveMode.Modified); // throws ConfigurationErrorsException
    ConfigurationManager.RefreshSection("userSettings");
    

    configurationErrorException.message为“根元素必须与引用文件“appSettings”(C:\myfile.xml第2行)的节的名称匹配”。该文件为:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <userSettings>
            <MyApplication.Properties.Settings>
                <setting name="SineWaveFrequency" serializeAs="String">
                    <value>6</value>
                </setting>
                <setting name="SineWaveAmplitude" serializeAs="String">
                    <value>6</value>
                </setting>
            </MyApplication.Properties.Settings>
        </userSettings>
    </configuration>
    

    是否有方法将此文件中的值导入到 MyApplication.Properties.Settings.Default 类,框架像在应用程序启动时加载配置文件一样处理所有XML反序列化?

    2 回复  |  直到 15 年前
        1
  •  7
  •   Pat    15 年前

    好吧,这是可行的:

    using System;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    using System.Xml.XPath;
    
    public static class SettingsIO
    {
        internal static void Import(string settingsFilePath)
        {
            if (!File.Exists(settingsFilePath))
            {
                throw new FileNotFoundException();
            }
    
            var appSettings = Properties.Settings.Default;
            try
            {
                var config = 
    ConfigurationManager.OpenExeConfiguration(
    ConfigurationUserLevel.PerUserRoamingAndLocal);
    
                string appSettingsXmlName = 
    Properties.Settings.Default.Context["GroupName"].ToString(); 
    // returns "MyApplication.Properties.Settings";
    
                // Open settings file as XML
                var import = XDocument.Load(settingsFilePath);
                // Get the whole XML inside the settings node
                var settings = import.XPathSelectElements("//" + appSettingsXmlName);
    
                config.GetSectionGroup("userSettings")
                    .Sections[appSettingsXmlName]
                    .SectionInformation
                    .SetRawXml(settings.Single().ToString());
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("userSettings");
    
                appSettings.Reload();
            }
            catch (Exception) // Should make this more specific
            {
                // Could not import settings.
                appSettings.Reload(); // from last set saved, not defaults
            }
        }
    
        internal static void Export(string settingsFilePath)
        {
            Properties.Settings.Default.Save();
            var config = 
    ConfigurationManager.OpenExeConfiguration(
    ConfigurationUserLevel.PerUserRoamingAndLocal);
            config.SaveAs(settingsFilePath);
        }
    }
    

    export方法创建如下文件:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <userSettings>
            <MyApplication.Properties.Settings>
                <setting name="SineWaveFrequency" serializeAs="String">
                    <value>1</value>
                </setting>
                <setting name="SineWaveAmplitude" serializeAs="String">
                    <value>100</value>
                </setting>
                <setting name="AdcShift" serializeAs="String">
                    <value>8</value>
                </setting>
                <setting name="ControlBitsCheckedIndices" serializeAs="String">
                    <value>0,1,2,3,5,6,7,8</value>
                </setting>
                <setting name="UpgradeSettings" serializeAs="String">
                    <value>False</value>
                </setting>
            </MyApplication.Properties.Settings>
        </userSettings>
    </configuration>
    

    import方法解析该文件,获取节点内的所有内容,将该XML放入相应部分的user.config文件中,然后重新加载properties.settings.default,以便从新的user.config文件中获取这些值。

        2
  •  0
  •   Martijn Pieters    12 年前

    PAT建议的解决方案:

    // Get the whole XML inside the settings node
    var settings = import.XPathSelectElements("//" + appSettingsXmlName);
    

    收益率 null . 我把它改成

    var settings = import.Element("configuration").Element("userSettings").Element(appSettingsXmlName);
    
    config.GetSectionGroup("userSettings")
          .Sections[appSettingsXmlName]
          .SectionInformation
          .SetRawXml(settings.ToString());
    

    而且效果很好。