我有以下问题: 我们有一个加载模块(附加组件)的应用程序。这些模块可能需要在app.config中输入(例如WCF配置)。因为模块是动态加载的,所以我不想在应用程序的app.config文件中包含这些条目。 我想做的是以下几点:
注意:我不想覆盖默认的app.config!
它应该透明地工作,以便例如ConfigurationManager.AppSettings使用该新文件。
ConfigurationManager.AppSettings
在评估此问题的过程中,我想出了与此处提供的解决方案相同的解决方案:使用nunit重新加载app.config。 不幸的是,它似乎没有任何作用,因为我仍然从正常的app.config中获取数据。
我使用以下代码对其进行了测试:
Console.WriteLine(ConfigurationManager.AppSettings["SettingA"]); Console.WriteLine(Settings.Default.Setting); var combinedConfig = string.Format(CONFIG2, CONFIG); var tempFileName = Path.GetTempFileName(); using (var writer = new StreamWriter(tempFileName)) { writer.Write(combinedConfig); } using(AppConfig.Change(tempFileName)) { Console.WriteLine(ConfigurationManager.AppSettings["SettingA"]); Console.WriteLine(Settings.Default.Setting); }
它打印两次相同的值,尽管它combinedConfig包含普通app.config之外的其他值。
combinedConfig
如果在首次使用配置系统之前就使用了链接问题中的技巧,则该技巧是可行的。在那之后,它不再起作用了。 原因: 存在一个ClientConfigPaths可缓存路径的类。因此,即使使用更改了路径SetData,也不会重新读取它,因为已经存在缓存的值。解决方案是也删除这些:
ClientConfigPaths
SetData
using System; using System.Configuration; using System.Linq; using System.Reflection; public abstract class AppConfig : IDisposable { public static AppConfig Change(string path) { return new ChangeAppConfig(path); } public abstract void Dispose(); private class ChangeAppConfig : AppConfig { private readonly string oldConfig = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString(); private bool disposedValue; public ChangeAppConfig(string path) { AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", path); ResetConfigMechanism(); } public override void Dispose() { if (!disposedValue) { AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", oldConfig); ResetConfigMechanism(); disposedValue = true; } GC.SuppressFinalize(this); } private static void ResetConfigMechanism() { typeof(ConfigurationManager) .GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, 0); typeof(ConfigurationManager) .GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, null); typeof(ConfigurationManager) .Assembly.GetTypes() .Where(x => x.FullName == "System.Configuration.ClientConfigPaths") .First() .GetField("s_current", BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, null); } } }
用法是这样的:
// the default app.config is used. using(AppConfig.Change(tempFileName)) { // the app.config in tempFileName is used } // the default app.config is used.
如果要在整个应用程序运行时更改使用的app.config,只需AppConfig.Change(tempFileName)在应用程序开始处放置而不使用的位置即可。
AppConfig.Change(tempFileName)