在运行时从不同的文件加载 Properties.Settings [英] Loading Properties.Settings from a different file at runtime
问题描述
有没有办法在运行时从默认 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.
我使用 Visual Studio 中的 Settings.Settings
GUI 为我创建我的 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.
我知道一种使用 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.
本质上,Properties.Settings
类是由 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(string filename)
函数.该函数接受一个配置文件名作为参数.它将解析文件并加载它在配置文件中遇到的任何设置.要恢复到原始配置,只需调用 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()
.
希望这可以帮助其他人!
Hope this might help someone else!
推荐答案
这取决于应用程序的类型:
It depends on the type of the application:
- Web 应用程序和Windows 应用程序 - 使用 configSource xml 属性,如果您愿意将配置文件存储在与应用程序相同的文件夹(或子文件夹)中
- 创建一个 settings provider 并实施 IApplicationSettingsProvider.示例 此处 和 此处.您可能还需要使用 IConfigurationManagerInternal 接口替换默认的 .NET 配置管理器.在实施提供商时,不要忘记区分用户设置和应用程序设置以及漫游配置文件.
- 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
- 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 类(默认设置提供程序)并将其更改为您的需要(您可能会发现一些有用的代码,并且可能需要复制它所依赖的所有类).
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屋!