Reputation: 1706
I am trying to use a external config file in my console application. My App.config looks like this.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="MyConfig" type="System.Configuration.NameValueFileSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="MyConfig2" type="System.Configuration.NameValueFileSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="MyConfig3" type="System.Configuration.NameValueFileSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</configSections>
<MyConfig configSource="MyCustomConfig.config"/>
<MyConfig2 configSource="MyCustomConfig2.config"/>
<MyConfig3 configSource="MyCustomConfig3.config"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup>
</configuration>
In the config file, I have few keys with duplicates which is expected.
<?xml version="1.0" encoding="utf-8" ?>
<MyConfig>
<add key="NodeName" value="node1"/>
<add key="NodeName" value="node2"/>
<add key="NodeName" value="node3"/>
<add key="NodeName" value="node4"/>
<add key="NodeName" value="node5"/>
<add key="NodeProperty1" value="value1"/>
<add key="NodeProperty2" value="value2"/>
<add key="NodeProperty3" value="value3"/>
</MyConfig>
I am trying to read the values for NodeName using below code.
var ConfigData = (NameValueCollection)ConfigurationManager.GetSection("MyConfig");
foreach (string Nodename in ConfigData.GetValues("NodeName"))
{
Console.WriteLine("Node Name:" + Nodename);
}
Using above code, I only get node5 instead of getting values node1 to node5. Even though GetValues is supposed to return a string array, the array itself has only 1 value. Please let me know what needs to be corrected so that I can read all the values.
I know that I can achieve the required results using a comma separated values, but the number of nodenames can grow to a large number is future. So I don't want someone setting up the config to make any errors when adding new node values as CSV. Hence I want pursue an option that will allow me to setup these as individual key value pair.
Upvotes: 2
Views: 1418
Reputation: 42493
There is no current build in configuration class that supports your scenario. You'll have to build your own.
I have created this implementation that returns the values of each key as an List<string>
.
public class NameValuesSection : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
var nameValues = new NameValuesCollection();
foreach (XmlNode xmlNode in section.ChildNodes)
{
switch(xmlNode.Name)
{
case "add":
List<string> values;
string key = xmlNode.Attributes["key"].Value;
string value = xmlNode.Attributes["value"].Value;
// see if we already had this key
if (nameValues.TryGetValue(
key,
out values))
{
// yep, let's add another value to the list
values.Add(value);
}
else
{
// nope, let's create the list and add it to the dictionary
values = new List<string>(new string[] { value });
nameValues.Add(key, values);
}
break;
default:
// only add is supported now, not remove and clear
throw new ArgumentException("is not a valid node ", xmlNode.Name);
}
}
return nameValues;
}
}
The type that is returned is a subclass of a generic dictionary:
public class NameValuesCollection : Dictionary<string, List<string>>
{
// add helper methods if needed
}
That might be useful when you want to expand various ways to access the values, for example by offering an option to get the first item or the last item.
In your config file you have to adapt your configsection
:
<section name="MyConfig1" type="ConsoleApplication1.NameValuesSection, ConsoleApplication1"/>
Type is build up from [namespace].[classname] and after the comma in which assembly your NameValuesSection is compiled to.
This how you can use that new section:
var data2 = ConfigurationManager.GetSection("MyConfig1");
var nvc = (NameValuesCollection)data2;
foreach (var keyname in nvc.Keys)
{
Console.Write("Node Name: {0} = [" , keyname);
// loop over all values in the List
foreach(var val in nvc[keyname])
{
Console.Write("{0};", val);
}
Console.WriteLine("]");
}
And this will be the output:
Node Name: NodeName = [node1;node2;node3;node4;node5;] Node Name: NodeProperty1 = [value1;] Node Name: NodeProperty2 = [value2;] Node Name: NodeProperty3 = [value3;]
Upvotes: 2