更改默认的app.config在运行时 [英] Change default app.config at runtime

查看:220
本文介绍了更改默认的app.config在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题:
我们有加载模块(附加功能)的应用程序。这些模块可能需要在App.config(如WCF配置)的条目。由于是动态加载的模块,我不希望在我的应用程序的app.config文件,这些条目。
我想这样做的是以下内容:

I have the following problem:
We have an application that loads modules (add ons). These modules might need entries in the app.config (e.g. WCF configuration). Because the modules are loaded dynamically, I don't want to have these entries in the app.config file of my application.
What I would like to do is the following:

  • 在内存中创建一个新的app.config它合并了部分配置从模块
  • 在告诉我的应用程序,以使用新的app.config

注:我不希望覆盖默认的app.config

Note: I do not want to overwrite the default app.config!

它应该工作透明,因此例如 ConfigurationManager.AppSettings 使用该新文件。

It should work transparently, so that for example ConfigurationManager.AppSettings uses that new file.

在我这个问题的评价,我想出了相同的解决方案,因为这里提供:刷新的app.config与NUnit的
不幸的是,它似乎并没有做任何事情,因为我还从正常的app.config获取数据。

During my evaluation of this problem, I came up with the same solution as is provided here: Reload app.config with nunit.
Unfortunately, it doesn't seem to do anything, because I still get the data from the normal app.config.

我用这个code来测试它:

I used this code to test it:

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);
}

它输出相同的值twices,虽然 combinedConfig 包含其他值比正常的app.config。

It prints the same values twices, although combinedConfig contains other values than the normal app.config.

推荐答案

如果在使用前配置系统使用的第一次在链接的问题的破解工作。在此之后,这是行不通的任何更多。
究其原因:
存在一类 ClientConfigPaths 的缓存路径。因此,即使更改路径与的SetData 之后,它不重读,因为那里已经存在的缓存值。解决的方法是删除这些,太:

The hack in the linked question works if it is used before the configuration system is used the first time. After that, it doesn't work any more.
The reason:
There exists a class ClientConfigPaths that caches the paths. So, even after changing the path with SetData, it is not re-read, because there already exist cached values. The solution is to remove these, too:

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);
        }
    }
}

使用方法是这样的:

Usage is like this:

// 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)而不使用在开始的地方您的应用程序。

If you want to change the used app.config for the whole runtime of your application, simply put AppConfig.Change(tempFileName) without the using somewhere at the start of your application.

这篇关于更改默认的app.config在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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