My question is about working with standard .NET configuration objects and custom configuration elements as well, (which one can define by extending the
The loaded configuration object appears to be a merged configuration object containing the setup present in the application config file (the the app.config or web.config file which a developer may have created) and what is defined in the machine.config file (the latter coming with the .NET Framework installation).
So, we can assume that the configuration is loaded in hierarchical manner with the machine.config first, and any user-defined configuration overlaying that default setup, and could be looked at like this:
As silver has pointed out, a well configured
ExeConfigurationFileMap could do the job, at a certain cost.
I have taken his example and made a working version of it.
Here are the two config files I have merged for my test purposes:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="custom" type="..." /> </configSections> <custom> <singleProperty id="main" value="BaseValue" /> <propertyCollection> <property id="1" value="One" /> <property id="4" value="Four" /> </propertyCollection> </custom> </configuration>
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="custom" type="..."/> </configSections> <custom> <singleProperty id="main" value="OverriddenValue" /> <propertyCollection> <property id="1" value="OverridenOne" /> <property id="2" value="Two" /> <property id="3" value="Three" /> </propertyCollection> </custom> </configuration>
And I used the following code to test the merged setup:
var map = new ExeConfigurationFileMap(); map.MachineConfigFilename = PathToCustomConfig; map.ExeConfigFilename = PathToAppConfig; var configuration = ConfigurationManager.OpenMappedExeConfiguration( map, ConfigurationUserLevel.None); var section = configuration.GetSection("custom") as CustomConfigSection; Assert.IsNotNull(section); Assert.AreEqual(section.SingleProperty.Value, "OverriddenValue"); Assert.AreEqual(section.PropertyCollection.Count, 4); // Needed to map the properties as dictionary, not to rely on the property order var values = section.PropertyCollection .Cast<SimpleConfigElement>() .ToDictionary(x => x.ID, x => x.Value); Assert.AreEqual(values["1"], "OverridenOne"); Assert.AreEqual(values["2"], "Two"); Assert.AreEqual(values["3"], "Three"); Assert.AreEqual(values["4"], "Four");
map.MachineConfigFilename = PathToCustomConfig;I assume I am removing any values that are set up by the real
machine.configfile. This could be error-prone and should be avoided for web applications, as most of them rely on what's in the real
app.configwill be named when the code is compiled (usually AssemblyName.exe.config)
I am still in the process of refining the technique, thus I will return to update this post once done.