我正在尝试从外部 app.config 文件的配置中复制 ConfigurationSection
,最终目标是将其合并到执行应用程序当前加载的配置中。
目的是允许加载到各个 AppDomain 中的众多库从执行应用程序接收配置并合并它们自己的 app.config 设置,以便读取任何设置都是一个简单的调用ConfigurationManager.AppSettings
或 ConfigurationManager.GetSection()
。
我遇到的问题是克隆 ConfigurationSection
。
我尝试过的:
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()
(使用任意参数组合)也不会填充该部分。
- 运行正常,但是
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()
行引发异常,指出无法添加已属于 Configuration 的 ConfigurationSection。
。问题是localConfig
没有该部分。即使添加localConfig.Remove("some.section");
也无法解决。 - 我还尝试了多种
*ConfigurationSource
对象的组合,看看它们是否有所不同,但没有任何效果。
- 这会在
通过诸如 ConfigurationManager.AppSettings.Set( "some key", "some value");
但使用 ConfigurationSections 似乎并不那么容易。
有没有办法将 ConfigurationSection
从一个配置复制、克隆和/或简单地合并到另一个配置中?
注释:
- 我不想合并物理文件。一切都应该在运行时发生并仅保留在内存中。
- 我不想编写一个自定义类来表示每个 ConfigurationSection。这些部分是通用的,并且对于执行应用程序来说是未知的。
最佳答案
我找到了一种合并 ConfigurationSection
的方法已从任何具有主执行应用程序加载配置的 app.config 文件中读取!
该方法使用 ConfigurationSectionCloner
扩展我的代码 #1来自Enterprise Library :
// 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 中异步执行此操作会导致争用问题,但这是另一个主题!
关于c# - 克隆通用 ConfigurationSection 而不使用自定义类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15640330/