克隆一个没有自定义类的通用ConfigurationSection

本文关键字:自定义 ConfigurationSection 一个 | 更新日期: 2023-09-27 18:06:09

我正在尝试从外部app.config文件的配置中复制ConfigurationSection,最终目标是将其合并到执行应用程序当前加载的配置中。

的目的是允许许多库,加载到单独的appdomain,从执行应用程序接收配置有自己的app.config设置合并,以便读取任何设置是一个简单的调用ConfigurationManager.AppSettingsConfigurationManager.GetSection()

我遇到的问题是克隆一个ConfigurationSection

我试过了:

  1. ConfigurationSectionCloner in Enterprise Library.

    Configuration externalConfig = ConfigurationManager.OpenExeConfiguration(externalLibPath);
    var section = externalConfig.GetSection("some.section");
    ConfigurationSectionCloner sectionCloner = new ConfigurationSectionCloner();
    section = sectionCloner.Clone(section);
    Configuration localConfig = ConfigurationManager.OpenExecConfiguration(ConfigurationUserLevel.None);
    localConfig.Sections.Add("some.section", section);
    
    • 这个运行正常,但是,localConfig.GetSection("some.section")ConfigurationManager.GetSection("some.section")都是空的。
    • 即使调用localConfig.Save()(使用任何参数组合)也不会填充该section。

  2. CompositeConfigurationSourceHandler in Enterprise Library

    SystemConfigurationSource localConfig = new SystemConfigurationSource();
    FileConfigurationSource externalConfig = new FileConfigurationSource(externalLibPath + ".config");
    CompositeConfigurationSourceHandler ccsh = new CompositeConfigurationSourceHandler(externalConfig);
    ConfigurationSection section = externalConfig.GetSection("some.section");
    if (!ccsh.CheckAddSection("some.section", section)) {
        try {
            localConfig.Add("some.section", section);
        } catch (Exception) { }
    }
    
    • 这会在localConfig.add()行抛出一个异常,说明Cannot add a ConfigurationSection that already belongs to the Configuration.。问题是localConfig 没有有该部分。即使添加localConfig.Remove("some.section");也无法解决。
    • 我也尝试了一些*ConfigurationSource对象的组合,看看它们是否有所不同,但没有。

appSettings块复制实际的ApplicationSettings,甚至从connectionStrings块复制ConnectionStrings是超级简单的调用,如ConfigurationManager.AppSettings.Set("some key", "some value");,但它似乎不那么容易与ConfigurationSections。

是否有一种方法来复制,克隆和/或只是简单地合并一个ConfigurationSection从一个配置到另一个?

指出:

    我不想合并物理文件。一切都应该在运行时发生,并且只保留在内存中。我不想写一个自定义类来表示每个ConfigurationSection。这些节将是通用的,对于执行的应用程序来说是未知的。

克隆一个没有自定义类的通用ConfigurationSection

我已经找到了一种方法来合并从任何app.config文件中读取的ConfigurationSection与主执行应用程序加载的配置!

该方法使用企业库中的ConfigurationSectionCloner扩展了#1的代码:

// open the external configuration
Configuration externalConfig = ConfigurationManager.OpenExeConfiguration(externalLibPath);
// get the section we're looking to clone & merge
var sectionToClone = externalConfig.GetSection(sectionName);
// "clone" the section; this will create a `DefaultSection` object - not a "pure clone" =[
ConfigurationSectionCloner sectionCloner = new ConfigurationSectionCloner();
var clonedSection = sectionCloner.Clone(sectionToClone);
// set the `Type` of the new section to the one we're cloning (most likely a NameValueCollection)
clonedSection.SectionInformation.Type = sectionToClone.SectionInformation.Type;
// set the new section's XML to match the original one (really? the cloner doesn't do this?!)
clonedSection.SectionInformation.SetRawXml(sectionToClone.SectionInformation.GetRawXml());
// open our local configuration (the "executing application's config)
Configuration localConfig = ConfigurationManager.OpenExecConfiguration(ConfigurationUserLevel.None);
// add the cloned section to it
localConfig.Sections.Add(sectionName, clonedSection);
// save the section (this can be any variation-of-parameters for `.Save()`)
localConfig.Save(ConfigurationSaveMode.Minimal);
// force ConfigurationManager to refresh the new section
ConfigurationManager.RefreshSection(sectionName);
奇怪的是,在我所有的测试中,上面的步骤都是所有必需的。每个节需要的主要操作是设置新节的Type、调用SetRawXml()和刷新该节。

这种方法的缺点是,与我最初的愿望相反,对localConfig.Save()的调用将它保存到磁盘上,覆盖了原始的app.config文件。在多个appdomain中异步执行此操作会导致争用问题,但这是另一个主题!