我正在尝试从外部app.config文件的配置中复制ConfigurationSection
,其最终目标是将其合并到正在执行的应用程序当前加载的配置中。
目的是允许加载到单个AppDomains中的大量库从正在执行的应用程序接收配置和将自己的app.config设置合并,以便读取任何设置是一个简单的调用ConfigurationManager.AppSettings
或ConfigurationManager.GetSection()
。
我遇到的问题是克隆ConfigurationSection
。
我尝试了什么:
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()
行引发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
从一个配置合并到另一个配置?
注意:
答案 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中异步执行此操作会导致争用问题,但这是一个不同的主题!