为了账号安全,请及时绑定邮箱和手机立即绑定

在运行时更改默认app.config

在运行时更改默认app.config

SMILET 2019-06-28 16:18:11
在运行时更改默认app.config我有以下问题:我们有一个加载模块的应用程序(添加ON)。这些模块可能需要app.config中的条目(例如,WCF配置)。由于模块是动态加载的,所以我不希望应用程序的app.config文件中有这些条目。我想做的是:在内存中创建一个新的app.config,它包含模块中的配置部分告诉我的应用程序使用那个新app.config注意:我不想覆盖默认app.config!它应该透明地工作,例如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以外的其他值。
查看完整描述

3 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

如果在第一次使用配置系统之前就使用了链接问题,那么链接问题中的黑客就能工作。在那之后,它就不再起作用了。
原因:
存在一个类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)在您的应用程序开始时不需要在某个地方使用。


查看完整回答
反对 回复 2019-06-28
  • 3 回答
  • 0 关注
  • 750 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信