强制ConfigurationManager重新加载所有部分

时间:2022-09-06 12:48:37

I am writing a configuration system in which the app.config file is dynamically constructed from various config fragments distributed across multiple locations. The system currently works as follows:

我正在编写一个配置系统,其中app.config文件是从分布在多个位置的各种配置片段动态构建的。该系统目前的工作原理如下:

  1. Bootstrapper builds configuration file.
  2. Bootstrapper构建配置文件。

  3. Bootstrapper initializes new AppDomain with new config file as the configuration file.
  4. Bootstrapper使用新的配置文件作为配置文件初始化新的AppDomain。

  5. As a result, new AppDomain is configured to use new config file and all works fine.
  6. 因此,新的AppDomain配置为使用新的配置文件,一切正常。

We'd like to move away from this multiple AppDomain approach; it adds a layer of complexity, especially when it comes to unmanaged libraries and other legacy code.

我们想摆脱这种多AppDomain方法;它增加了一层复杂性,特别是涉及非托管库和其他遗留代码时。

In moving to one AppDomain, the workflow would change to:

在迁移到一个AppDomain时,工作流程将更改为:

  1. Bootstrapper builds configuration file.
  2. Bootstrapper构建配置文件。

  3. Bootstrapper merges the configuration file into its own configuration file.
  4. Bootstrapper将配置文件合并到自己的配置文件中。

  5. Bootstrapper refreshes its ConfigurationManager cache.
  6. Bootstrapper刷新其ConfigurationManager缓存。

  7. Bootstrapper launches main app in the same AppDomain.
  8. Bootstrapper在同一个AppDomain中启动主应用程序。

It seems that the ConfigurationManager caches sections in memory. So for example, if I read the AppSettings before step #3, I have to call: ConfigurationManager.RefreshSection("appSettings"); In fact, I have to make sure that any section that has been used by the bootstrapper, is refreshed.

似乎ConfigurationManager在内存中缓存部分。例如,如果我在步骤#3之前阅读AppSettings,我必须调用:ConfigurationManager.RefreshSection(“appSettings”);实际上,我必须确保刷新了引导程序使用的任何部分。

I am able to iterate over all of the config sections in the new config file and force refresh them, but, this forces the configuration manager to load any assemblies referenced in the config file. I'd like to defer this if possible. If there a way to invalidate what the ConfigurationManager currently has in memory?

我能够迭代新配置文件中的所有配置部分并强制刷新它们,但是,这会强制配置管理器加载配置文件中引用的任何程序集。如果可能的话,我想推迟这个。如果有办法使ConfigurationManager当前在内存中的内容无效?

1 个解决方案

#1


I know the question was posted a long time ago but I hope this answer will still be useful.

我知道这个问题是很久以前发布的,但我希望这个答案仍然有用。

It seems there is no standard way to do this. However, by accessing internal fields and types of the ConfigurationManager class I was able to list all loaded sections. This is how I did it :

似乎没有标准的方法来做到这一点。但是,通过访问ConfigurationManager类的内部字段和类型,我能够列出所有已加载的部分。我就这样做了:

private static IEnumerable<string> GetLoadedSections()
{
    // s_configSystem can be null if the ConfigurationManager is not properly loaded. Accessing the AppSettings *should* do the trick.
    var appSettings = ConfigurationManager.AppSettings;

    FieldInfo s_configSystemField = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
    object s_configSystem = s_configSystemField.GetValue(null);
    FieldInfo _completeConfigRecordField = s_configSystem.GetType().GetField("_completeConfigRecord", BindingFlags.NonPublic | BindingFlags.Instance);
    object _completeConfigRecord = _completeConfigRecordField.GetValue(s_configSystem);
    FieldInfo _sectionRecordsField = _completeConfigRecord.GetType().GetField("_sectionRecords", BindingFlags.NonPublic | BindingFlags.Instance);
    Hashtable _sectionRecords = (Hashtable)_sectionRecordsField.GetValue(_completeConfigRecord);
    return _sectionRecords.Keys.OfType<string>();
}

The "system.diagnostics" section seems to always be loaded. The "appSettings" section is also loaded since I have to access it to make it work consistently.

似乎总是加载“system.diagnostics”部分。 “appSettings”部分也已加载,因为我必须访问它以使其一致地工作。

This works on my machine (.NET 4.5) but since it relies on internal stuff, it can break at any time if Microsoft decide to change the implementation of the ConfigurationManager class.

这适用于我的机器(.NET 4.5),但由于它依赖于内部资源,如果Microsoft决定更改ConfigurationManager类的实现,它可以随时中断。

#1


I know the question was posted a long time ago but I hope this answer will still be useful.

我知道这个问题是很久以前发布的,但我希望这个答案仍然有用。

It seems there is no standard way to do this. However, by accessing internal fields and types of the ConfigurationManager class I was able to list all loaded sections. This is how I did it :

似乎没有标准的方法来做到这一点。但是,通过访问ConfigurationManager类的内部字段和类型,我能够列出所有已加载的部分。我就这样做了:

private static IEnumerable<string> GetLoadedSections()
{
    // s_configSystem can be null if the ConfigurationManager is not properly loaded. Accessing the AppSettings *should* do the trick.
    var appSettings = ConfigurationManager.AppSettings;

    FieldInfo s_configSystemField = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
    object s_configSystem = s_configSystemField.GetValue(null);
    FieldInfo _completeConfigRecordField = s_configSystem.GetType().GetField("_completeConfigRecord", BindingFlags.NonPublic | BindingFlags.Instance);
    object _completeConfigRecord = _completeConfigRecordField.GetValue(s_configSystem);
    FieldInfo _sectionRecordsField = _completeConfigRecord.GetType().GetField("_sectionRecords", BindingFlags.NonPublic | BindingFlags.Instance);
    Hashtable _sectionRecords = (Hashtable)_sectionRecordsField.GetValue(_completeConfigRecord);
    return _sectionRecords.Keys.OfType<string>();
}

The "system.diagnostics" section seems to always be loaded. The "appSettings" section is also loaded since I have to access it to make it work consistently.

似乎总是加载“system.diagnostics”部分。 “appSettings”部分也已加载,因为我必须访问它以使其一致地工作。

This works on my machine (.NET 4.5) but since it relies on internal stuff, it can break at any time if Microsoft decide to change the implementation of the ConfigurationManager class.

这适用于我的机器(.NET 4.5),但由于它依赖于内部资源,如果Microsoft决定更改ConfigurationManager类的实现,它可以随时中断。