Загрузка Properties.Settings из другого файла во время выполнения

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

Я использую графический интерфейс Settings.Settingsв Visual Studio, чтобы создать для себя файл 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вместо использования файла app.configпо умолчанию. Форматы конфигурационных файлов будут одинаковыми, но значения параметров будут другими.

Я знаю способ сделать это с помощью ConfigurationManager.OpenExeConfiguration(configFile);. Однако в тестах, которые я запускал, он не обновляет объект Properties.Settings.Default, чтобы отразить новые значения из файла конфигурации.


Подумав об этом немного дольше, я смог придумать решение, которое мне нравится немного больше. Я уверен, что у него есть некоторые подводные камни, но я думаю, что он будет работать для того, что мне нужно.

По сути, класс Properties.Settingsавтоматически генерируется Visual Studio; он генерирует для вас код класса. Мне удалось найти, где был сгенерирован код, и добавить несколько вызовов функций для самостоятельной загрузки файла конфигурации. Вот мое дополнение:

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). Функция принимает имя файла конфигурации в качестве параметра. Он проанализирует файл и загрузит все настройки, которые встретится в файле конфигурации. Чтобы вернуться к исходной конфигурации, просто позвоните Properties.Settings.Reload().

Надеюсь, это может помочь кому-то еще!

6
задан beefsupreme 31 July 2012 в 03:16
поделиться