我有以下问题:

  • 创建一个新的应用程序.内存中包含模块配置部分的配置
  • 告诉我的应用程序使用那个新应用程序.配置

注意:我不想覆盖默认apply.配置!

它应该透明地工作,以便例如ConfigurationManager.AppSettings使用该新文件.

在我对这个问题的判断中,我提出了与这里提供的相同的解决方案:Reload app.config with nunit

我使用此代码对其进行测试:

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包含普通应用程序以外的其他值.配置.

推荐答案

如果在第一次使用配置系统之前就使用了链接问题中的hack,那么它就会起作用.在那之后,它就不起作用了

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)而不使用Using即可.

.net相关问答推荐

PowerShell 5.1和7在使用证书时的区别

在本地运行 Azure 函数会在 .NET7 升级后出现无运行时错误

如何在 .net MAUI 中删除不需要编译的平台?

当 Func 委托需要接口作为参数时,它是如何工作的?

HttpClient 请求抛出 IOException

AutoMapper 的替代品

mstest.exe 在哪里?

ILMerge 最佳实践

实例化具有运行时确定类型的对象

.NET 等价于旧的 vb left(string, length) 函数

什么决定了 Path.GetTempPath() 的返回值?

运算符重载 ==, !=, Equals

.NET 反射的成本是多少?

从 Windows 窗体打开 URL

获取磁盘上文件的大小

我应该如何删除 DbSet 中的所有元素?

如何获取命名空间中的所有类?

并发字典正确用法

对构造函数进行单元测试重要吗?

C#/.NET 中仅命名空间的类可见性?