2

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

目的是允许加载到单个 AppDomain 中的大量库从执行的应用程序接收配置,合并它们自己的 app.config 设置,以便读取任何设置只需调用ConfigurationManager.AppSettingsor即可ConfigurationManager.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. 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对象组合,看看它们是否有所作为,但没有一个有所作为。

从块中复制实际的 ApplicationSettings appSettings,甚至从块中复制 ConnectionStringsconnectionStrings是非常简单的调用,ConfigurationManager.AppSettings.Set("some key", "some value");但使用 ConfigurationSections 似乎并不容易。

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

笔记:

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

1 回答 1

4

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

该方法使用 Enterprise Library 中的 #1 扩展了我ConfigurationSectionCloner代码

// 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 中异步执行此操作会导致争用问题,但这是一个不同的主题!

于 2013-03-28T01:41:30.387 回答