在运行时从不同的文件加载Properties.Settings [英] Loading Properties.Settings from a different file at runtime

查看:115
本文介绍了在运行时从不同的文件加载Properties.Settings的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法从比默认的App.config 文件在运行其他不同的文件中加载设置?我想默认的配置文件被加载后,要做到这一点。

Is there any way to load settings from a different file other than the default App.config file at runtime? I'd like to do this after the default config file is loaded.

我用 Settings.Settings GUI在Visual Studio中创建我的的App.config 文件给我。该配置文件最终看起来是这样的:

I use the Settings.Settings GUI in Visual Studio to create my App.config file for me. The config file ends up looking like this:

    <?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>

在代码中,我能够获得这样的设置:

In code, I'm able to access the settings like this:

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



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

The idea is that when the application is run, I should be able to specify a config file at run time and have the application load the config file into the Properties.Settings.Default object instead of using the default app.config file. The formats of the config files would be the same, but the values of the settings would be different.

我知道的方式与<$ C $要做到这一点C> ConfigurationManager.OpenExeConfiguration(CONFIGFILE); 。然而,在我进行的测试,它不会更新 Properties.Settings.Default 对象从配置文件反映新的值。

I know of a way to do this with the ConfigurationManager.OpenExeConfiguration(configFile);. However, in the tests that I've run, it doesn't update the Properties.Settings.Default object to reflect the new values from the config file.

想着这多一点的时间之后,我已经能够拿出我喜欢的好一点的解决方案。我敢肯定,它有一些缺陷,但我认为它会为我需要做的工作。

After thinking about this a bit longer, I've been able to come up with a solution that I like a little better. I'm sure it has some pitfalls, but I think it'll work for what I need it to do.

从本质上讲,属性。设置类会自动由Visual Studio生成;它生成的类为你的代码。我能找到的地方生成的代码,并添加一些函数调用来加载自身的配置文件。这里是我的另外:

Essentially, the Properties.Settings class is automatically generated by Visual Studio; it generates the code for the class for you. I was able to find where the code was generated and add a few function calls to load a config file on its own. Here's my addition:

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(字符串文件名)功能。所述函数接受配置文件名作为参数。它会解析该文件并加载它在配置文件中遇到的任何设置。要恢复到原来的配置,只需拨打 Properties.Settings.Reload()

The code I added exposes an Properties.Settings.Load(string filename) function. The function accepts a config filename as a parameter. It will parse the file and load up any settings it encounters in the config file. To revert back to the original configuration, simply call Properties.Settings.Reload().

希望这可以帮助!别人

推荐答案

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

It depends on the type of the application:


  1. Web应用程序和放大器; Windows应用程序 - 使用 configSource XML属性,如果你愿意在同一个文件夹中的配置文件(或子文件夹)作为应用程序

  2. 创建一个的设置提供并还实现的 IApplicationSettingsProvider 。样品这里和的此处。您可能还需要使用的 IConfigurationManagerInternal 接口来取代默认的.NET配置管理器。在实施供应商不要忘了让用户设置和应用程序设置和漫游配置文件之间的差异。

  1. Web Application & Windows Application - use the configSource xml attribute if you are willing to store the config files in the same folder (or subfolders) as the application
  2. Create a settings provider and also implement IApplicationSettingsProvider. Samples here and here. You might also need to use the IConfigurationManagerInternal interface to replace the default .NET configuration manager. When implementing the provider don't forget to make a difference between user settings and application settings and the roaming profiles.

如果你想上手迅速刚反编译 LocalFileSettingsProvider 类(默认设置提供程序),并将其更改为您的需要(您可能会发现一些useles代码,并可能需要复制所有它所依赖的类)的。

If you want to get started quickly just decompile the LocalFileSettingsProvider class (the default settings provider) and change it to your needs (you might find some useles code and might need to replicate all of the classes on which it depends).

好运气

这篇关于在运行时从不同的文件加载Properties.Settings的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆