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

时间:2013-03-26 14:59:47

标签: c# .net app-config configurationmanager

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

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

我遇到的问题是克隆ConfigurationSection

我尝试了什么:

    企业库中的
  1. ConfigurationSectionCloner

    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()(带有任何参数组合)也不会填充该部分
  2. 企业资料库中的
  3. CompositeConfigurationSourceHandler

    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个对象的组合,看看它们是否有所作为但是没有。
  4. appSettings块复制实际的ApplicationSettings,甚至从connectionStrings块复制ConnectionStrings都是非常简单的,只需ConfigurationManager.AppSettings.Set("some key", "some value");这样的调用,但是对于ConfigurationSections来说似乎不那么容易

    有没有办法复制,克隆和/或只是将ConfigurationSection从一个配置合并到另一个配置?

    注意:

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

1 个答案:

答案 0 :(得分:2)

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

该方法使用ConfigurationSectionCloner中的Enterprise Library扩展了#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文件。在多个AppDomains中异步执行此操作会导致争用问题,但这是一个不同的主题!