强制 ConfigurationManager 重新加载所有部分

发布于 2024-07-25 19:11:11 字数 825 浏览 8 评论 0原文

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

  1. Bootstrapper 构建配置文件。
  2. Bootstrapper 使用新的配置文件作为配置文件来初始化新的 AppDomain。
  3. 因此,新的 AppDomain 配置为使用新的配置文件,并且一切正常。

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

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

  1. Bootstrapper 构建配置文件。
  2. Bootstrapper 将配置文件合并到自己的配置文件中。
  3. Bootstrapper 刷新其 ConfigurationManager 缓存。
  4. Bootstrapper 在同一 AppDomain 中启动主应用程序。

看来 ConfigurationManager 将部分缓存在内存中。 例如,如果我在步骤 #3 之前读取 AppSettings,我必须调用: ConfigurationManager.RefreshSection("appSettings"); 事实上,我必须确保已使用的任何部分由引导程序刷新。

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

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:

  1. Bootstrapper builds configuration file.
  2. Bootstrapper initializes new AppDomain with new config file as the configuration file.
  3. As a result, new AppDomain is configured to use new config file and all works fine.

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.

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

  1. Bootstrapper builds configuration file.
  2. Bootstrapper merges the configuration file into its own configuration file.
  3. Bootstrapper refreshes its ConfigurationManager cache.
  4. Bootstrapper launches main app in the same 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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

简单爱 2024-08-01 19:11:11

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

似乎没有标准方法可以做到这一点。 但是,通过访问 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>();
}

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

这适用于我的计算机(.NET 4.5),但由于它依赖于内部内容,因此如果 Microsoft 决定更改 ConfigurationManager 类的实现,它可能随时中断。

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 :

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文