加载Properties.Settings在运行时从另一个文件

时间:2012-07-30 18:45:07

标签: c# app-config

有没有办法在运行时从默认App.config文件以外的其他文件加载设置?我想在加载默认配置文件后执行此操作。

我使用Visual Studio中的Settings.Settings GUI为我创建App.config文件。配置文件最终看起来像这样:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
            <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="SnipetTester.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
    </configSections>
      <applicationSettings>
        <SnipetTester.Properties.Settings>
          <setting name="SettingSomething" serializeAs="String">
            <value>1234</value>
          </setting>
        </SnipetTester.Properties.Settings>
      </applicationSettings>
    </configuration>

在代码中,我可以访问如下设置:

Console.WriteLine("Default setting value:  " + Properties.Settings.Default.SettingSomething);

我的想法是,当应用程序运行时,我应该能够在运行时指定配置文件,并让应用程序将配置文件加载到Properties.Settings.Default对象中,而不是使用默认的{{1}文件。配置文件的格式是相同的,但设置的值会有所不同。

我知道使用app.config执行此操作的方法。但是,在我运行的测试中,它不会更新ConfigurationManager.OpenExeConfiguration(configFile);对象以反映配置文件中的新值。


在考虑了这个问题之后,我已经能够提出一个我更喜欢的解决方案了。我确信它有一些陷阱,但我认为这对我需要做的事情有用。

基本上,Properties.Settings.Default类是由Visual Studio自动生成的;它为您生成类的代码。我能够找到代码生成的位置,并添加一些函数调用来自行加载配置文件。这是我的补充:

Properties.Settings

我添加的代码公开了internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { //Parses a config file and loads its settings public void Load(string filename) { System.Xml.Linq.XElement xml = null; try { string text = System.IO.File.ReadAllText(filename); xml = System.Xml.Linq.XElement.Parse(text); } catch { //Pokemon catch statement (gotta catch 'em all) //If some exception occurs while loading the file, //assume either the file was unable to be read or //the config file is not in the right format. //The xml variable will be null and none of the //settings will be loaded. } if(xml != null) { foreach(System.Xml.Linq.XElement currentElement in xml.Elements()) { switch (currentElement.Name.LocalName) { case "userSettings": case "applicationSettings": foreach (System.Xml.Linq.XElement settingNamespace in currentElement.Elements()) { if (settingNamespace.Name.LocalName == "SnipetTester.Properties.Settings") { foreach (System.Xml.Linq.XElement setting in settingNamespace.Elements()) { LoadSetting(setting); } } } break; default: break; } } } } //Loads a setting based on it's xml representation in the config file private void LoadSetting(System.Xml.Linq.XElement setting) { string name = null, type = null, value = null; if (setting.Name.LocalName == "setting") { System.Xml.Linq.XAttribute xName = setting.Attribute("name"); if (xName != null) { name = xName.Value; } System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs"); if (xSerialize != null) { type = xSerialize.Value; } System.Xml.Linq.XElement xValue = setting.Element("value"); if (xValue != null) { value = xValue.Value; } } if (string.IsNullOrEmpty(name) == false && string.IsNullOrEmpty(type) == false && string.IsNullOrEmpty(value) == false) { switch (name) { //One of the pitfalls is that everytime you add a new //setting to the config file, you will need to add another //case to the switch statement. case "SettingSomething": this[name] = value; break; default: break; } } } } 函数。该函数接受配置文件名作为参数。它将解析文件并加载它在配置文件中遇到的任何设置。要恢复原始配置,只需致电Properties.Settings.Load(string filename)

希望这可能有助于其他人!

3 个答案:

答案 0 :(得分:1)

使用ExeConfigurationFileMap和ConfigurationManager.OpenMappedExeConfiguration。

请参阅Cracking the Mysteries of .Net 2.0 Configuration

  

ExeConfigurationFileMap允许您专门配置   机器,exe,漫游和本地配置的确切路径名   调用时,文件,所有在一起或零碎   OpenMappedExeConfiguration()。您无需指定全部   文件,但所有文件将被识别和合并时   配置对象已创建。使用时   OpenMappedExeConfiguration,重要的是要了解所有   通过您请求的级别的配置级别将始终   合并。如果指定自定义exe和本地配置文件,   但是不要指定机器和漫游文件,默认机器和   将找到漫游文件并与指定的exe和用户合并   文件。如果指定的文件,这可能会产生意外的后果   没有与默认文件保持同步。

答案 1 :(得分:1)

这取决于应用程序的类型:

  1. 网络应用程序&amp; Windows应用程序 - 如果您愿意将配置文件存储在与应用程序相同的文件夹(或子文件夹)中,请使用configSource xml属性
  2. 创建settings provider并实施IApplicationSettingsProvider。样本herehere。您可能还需要使用IConfigurationManagerInternal接口来替换默认的.NET配置管理器。实施提供商时,不要忘记在用户设置和应用程序设置以及漫游配置文件之间做出改变。
  3. 如果您想快速入门,只需反编译LocalFileSettingsProvider类(默认设置提供程序)并根据需要进行更改(您可能会发现一些useles代码,可能需要复制它所有的类)取决于)。

    祝你好运

答案 2 :(得分:0)

您可以添加类型,这样您就不必每次都手动更新来源。

`private void LoadSetting(System.Xml.Linq.XElement setting)         {             string name = null,type = null;             string value = null;

        if (setting.Name.LocalName == "setting")
        {
            System.Xml.Linq.XAttribute xName = setting.Attribute("name");
            if (xName != null)
            {
                name = xName.Value;
            }

            System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs");
            if (xSerialize != null)
            {
                type = xSerialize.Value;
            }

            System.Xml.Linq.XElement xValue = setting.Element("value");
            if (xValue != null)
            {
                if (this[name].GetType() == typeof(System.Collections.Specialized.StringCollection))
                {
                    foreach (string s in xValue.Element("ArrayOfString").Elements())
                    {
                        if (!((System.Collections.Specialized.StringCollection)this[name]).Contains(s))
                            ((System.Collections.Specialized.StringCollection)this[name]).Add(s);
                    }
                }
                else
                {
                    value = xValue.Value;
                }

                if (this[name].GetType() == typeof(int))
                {
                    this[name] = int.Parse(value);
                }
                else if (this[name].GetType() == typeof(bool))
                {
                    this[name] = bool.Parse(value);
                }
                else
                {
                    this[name] = value;
                }

            }
        }`