App.config 将嵌套组添加到现有节点
App.config add nested group to existing node
我必须在根设置组中保存 2 组不同的设置。它应该看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
........................
some_settings
........................
</sectionGroup>
<sectionGroup name="GROUP_2">
........................
some_other_settings
........................
</sectionGroup>
</sectionGroup>
</configSections>
................................
other_system_tags
................................
</configuration>
细微差别是我必须在我的代码中的不同地方一个接一个地保存它。 (例如,GROUP_1 可以是连接字符串,GROUP_2 是一些环境设置,它们一起由用户在我的应用程序的不同部分填写)
我做了这个简单的测试class得到了预期的结果
[TestFixture]
public class Tttt
{
private string ROOT_GROUP = "ROOT_GROUP";
private string GROUP_1 = "GROUP_1";
private string GROUP_2 = "GROUP_2";
[Test]
public void SaveSettingsGroups()
{
SaveGroup1();
SaveGroup2();
Assert.True(true);
}
private Configuration GetConfig()
{
var configFilePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
var map = new ExeConfigurationFileMap { ExeConfigFilename = configFilePath };
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
return config;
}
private void SaveGroup1()
{
var config = GetConfig();
var root = new UserSettingsGroup();
config.SectionGroups.Add(ROOT_GROUP, root);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_1, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested.Name);
}
private void SaveGroup2()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_2, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested.Name);
}
}
但由于某些原因,此代码的结果不同
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
........................
some_settings
........................
</sectionGroup>
</sectionGroup>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_2">
........................
some_other_settings
........................
</sectionGroup>
</sectionGroup>
</configSections>
................................
other_system_tags
................................
</configuration>
ROOT_GROUP 节点是重复的,当然 visual studio 抛出一个异常 ROOT_GROUP 已经存在。显然,当我将新的嵌套组添加到现有根组然后保存它时,我的问题隐藏在方法 SaveGroup2() 中 - 但为什么呢?
UPD
我刚刚添加了新方法
private void SaveGroup3()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested1 = root.SectionGroups.Get(0);
var nested2 = new UserSettingsGroup();
var nested3 = new UserSettingsGroup();
nested1.SectionGroups.Add("GROUP_2", nested2);
root.SectionGroups.Add("GROUP_3", nested3);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested2.Name);
ConfigurationManager.RefreshSection(nested3.Name);
}
并在测试中替换它
[Test]
public void SaveSettingsGroups()
{
SaveGroup1();
SaveGroup3();
Assert.True(true);
}
并得到了这个奇怪的行为
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
<sectionGroup name="GROUP_2">
</sectionGroup>
</sectionGroup>
<sectionGroup name="GROUP_3">
</sectionGroup>
</sectionGroup>
如您所见,奇怪的是结果完全在意料之中。 ROOT_GROUP 不是重复的,因为我需要它,但为什么它在 SaveGroup2() 中呢?我是否遗漏了 SaveGroup2() 中的某些内容?
UPD2 - 破解
只是尝试了一个简单的想法 - 如果我在向其添加新的嵌套元素之前清除 root_group 会怎么样?
private void SaveGroup2()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested = new ConfigurationSectionGroup();
//Copy exiting nested groups to array
var gr = new ConfigurationSectionGroup[5];
root.SectionGroups.CopyTo(gr,0);
gr[1] = nested;
//<!----
root.SectionGroups.Clear();
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
root.SectionGroups.Add(gr[0].Name, gr[0]);
root.SectionGroups.Add(GROUP_2, gr[1]);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}
你怎么猜 - 它有效!
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
</sectionGroup>
<sectionGroup name="GROUP_2" type="System.Configuration.ConfigurationSectionGroup, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" >
</sectionGroup>
</sectionGroup>
我认为它看起来像是一个错误,或者我遗漏了一些隐藏的东西。有人可以解释一下我做错了什么吗?
在您的第一次更新中,您在 root 下的第一个条目下添加了 GROUP_2:
//nested1 is now the first entry under root due to Get(0)
var nested1 = root.SectionGroups.Get(0);
var nested2 = new UserSettingsGroup();
var nested3 = new UserSettingsGroup();
//I think you meant root here instead of nested1.
nested1.SectionGroups.Add("GROUP_2", nested2);
我花了一段时间才弄清楚发生了什么事,tl;dr 对我来说,框架代码本身存在问题,尤其是 method WriteUnwrittenConfigDeclarationsRecursive(SectionUpdates declarationUpdates, XmlUtilWriter utilWriter, int linePosition, int indent, bool skipFirstIndent)
内部class MgmtConfigurationRecord
。我不想写很长的故事,但如果您愿意,可以调试 .Net 框架代码并亲眼看看。
您可以通过以下方式修复您的代码:
1.将所有组一起保存
private void SaveGroups()
{
var config = GetConfig();
var root = new ConfigurationSectionGroup();
config.SectionGroups.Add(ROOT_GROUP, root);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_1, nested);
nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_2, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}
2。在添加新项目之前删除现有的组项目
private void SaveGroup2()
{
var config = GetConfig();
var root = config.SectionGroups[ROOT_GROUP];
var existingGroups = new Dictionary<string, ConfigurationSectionGroup>();
while (root.SectionGroups.Count > 0)
{
existingGroups.Add(root.SectionGroups.Keys[0], root.SectionGroups[0]);
root.SectionGroups.RemoveAt(0);
}
config.Save(ConfigurationSaveMode.Modified);
existingGroups.Add(GROUP_2, new UserSettingsGroup());
foreach (var key in existingGroups.Keys)
{
existingGroups[key].ForceDeclaration(true);
root.SectionGroups.Add(key, existingGroups[key]);
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}
我必须在根设置组中保存 2 组不同的设置。它应该看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
........................
some_settings
........................
</sectionGroup>
<sectionGroup name="GROUP_2">
........................
some_other_settings
........................
</sectionGroup>
</sectionGroup>
</configSections>
................................
other_system_tags
................................
</configuration>
细微差别是我必须在我的代码中的不同地方一个接一个地保存它。 (例如,GROUP_1 可以是连接字符串,GROUP_2 是一些环境设置,它们一起由用户在我的应用程序的不同部分填写)
我做了这个简单的测试class得到了预期的结果
[TestFixture]
public class Tttt
{
private string ROOT_GROUP = "ROOT_GROUP";
private string GROUP_1 = "GROUP_1";
private string GROUP_2 = "GROUP_2";
[Test]
public void SaveSettingsGroups()
{
SaveGroup1();
SaveGroup2();
Assert.True(true);
}
private Configuration GetConfig()
{
var configFilePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
var map = new ExeConfigurationFileMap { ExeConfigFilename = configFilePath };
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
return config;
}
private void SaveGroup1()
{
var config = GetConfig();
var root = new UserSettingsGroup();
config.SectionGroups.Add(ROOT_GROUP, root);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_1, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested.Name);
}
private void SaveGroup2()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_2, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested.Name);
}
}
但由于某些原因,此代码的结果不同
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
........................
some_settings
........................
</sectionGroup>
</sectionGroup>
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_2">
........................
some_other_settings
........................
</sectionGroup>
</sectionGroup>
</configSections>
................................
other_system_tags
................................
</configuration>
ROOT_GROUP 节点是重复的,当然 visual studio 抛出一个异常 ROOT_GROUP 已经存在。显然,当我将新的嵌套组添加到现有根组然后保存它时,我的问题隐藏在方法 SaveGroup2() 中 - 但为什么呢?
UPD 我刚刚添加了新方法
private void SaveGroup3()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested1 = root.SectionGroups.Get(0);
var nested2 = new UserSettingsGroup();
var nested3 = new UserSettingsGroup();
nested1.SectionGroups.Add("GROUP_2", nested2);
root.SectionGroups.Add("GROUP_3", nested3);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(nested2.Name);
ConfigurationManager.RefreshSection(nested3.Name);
}
并在测试中替换它
[Test]
public void SaveSettingsGroups()
{
SaveGroup1();
SaveGroup3();
Assert.True(true);
}
并得到了这个奇怪的行为
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1">
<sectionGroup name="GROUP_2">
</sectionGroup>
</sectionGroup>
<sectionGroup name="GROUP_3">
</sectionGroup>
</sectionGroup>
如您所见,奇怪的是结果完全在意料之中。 ROOT_GROUP 不是重复的,因为我需要它,但为什么它在 SaveGroup2() 中呢?我是否遗漏了 SaveGroup2() 中的某些内容?
UPD2 - 破解
只是尝试了一个简单的想法 - 如果我在向其添加新的嵌套元素之前清除 root_group 会怎么样?
private void SaveGroup2()
{
var config = GetConfig();
var root = config.GetSectionGroup(ROOT_GROUP);
var nested = new ConfigurationSectionGroup();
//Copy exiting nested groups to array
var gr = new ConfigurationSectionGroup[5];
root.SectionGroups.CopyTo(gr,0);
gr[1] = nested;
//<!----
root.SectionGroups.Clear();
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
root.SectionGroups.Add(gr[0].Name, gr[0]);
root.SectionGroups.Add(GROUP_2, gr[1]);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}
你怎么猜 - 它有效!
<sectionGroup name="ROOT_GROUP">
<sectionGroup name="GROUP_1" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
</sectionGroup>
<sectionGroup name="GROUP_2" type="System.Configuration.ConfigurationSectionGroup, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" >
</sectionGroup>
</sectionGroup>
我认为它看起来像是一个错误,或者我遗漏了一些隐藏的东西。有人可以解释一下我做错了什么吗?
在您的第一次更新中,您在 root 下的第一个条目下添加了 GROUP_2:
//nested1 is now the first entry under root due to Get(0)
var nested1 = root.SectionGroups.Get(0);
var nested2 = new UserSettingsGroup();
var nested3 = new UserSettingsGroup();
//I think you meant root here instead of nested1.
nested1.SectionGroups.Add("GROUP_2", nested2);
我花了一段时间才弄清楚发生了什么事,tl;dr 对我来说,框架代码本身存在问题,尤其是 method WriteUnwrittenConfigDeclarationsRecursive(SectionUpdates declarationUpdates, XmlUtilWriter utilWriter, int linePosition, int indent, bool skipFirstIndent)
内部class MgmtConfigurationRecord
。我不想写很长的故事,但如果您愿意,可以调试 .Net 框架代码并亲眼看看。
您可以通过以下方式修复您的代码:
1.将所有组一起保存
private void SaveGroups()
{
var config = GetConfig();
var root = new ConfigurationSectionGroup();
config.SectionGroups.Add(ROOT_GROUP, root);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
var nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_1, nested);
nested = new UserSettingsGroup();
root.SectionGroups.Add(GROUP_2, nested);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}
2。在添加新项目之前删除现有的组项目
private void SaveGroup2()
{
var config = GetConfig();
var root = config.SectionGroups[ROOT_GROUP];
var existingGroups = new Dictionary<string, ConfigurationSectionGroup>();
while (root.SectionGroups.Count > 0)
{
existingGroups.Add(root.SectionGroups.Keys[0], root.SectionGroups[0]);
root.SectionGroups.RemoveAt(0);
}
config.Save(ConfigurationSaveMode.Modified);
existingGroups.Add(GROUP_2, new UserSettingsGroup());
foreach (var key in existingGroups.Keys)
{
existingGroups[key].ForceDeclaration(true);
root.SectionGroups.Add(key, existingGroups[key]);
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(root.Name);
}