I am trying to create a custom configuration that looks like this.
<configuration>
<configSections>
<section name="actions" type="ConfigurationTest.ActionsConfig, UnitTestExperiments" />
<section name="action" type="ConfigurationTest.ActionConfig, UnitTestExperiments"/>
</configSections>
<actions poolSize="100">
<action name="a1" impl="some.class1">
<add name="key11" value="value11"/>
<add name="key12" value="key12"/>
</action>
<action name="a2" impl="some.class2">
<add name="key21" value="value21"/>
<add name="key22" value="key22"/>
</action>
</actions>
</configuration>
Here the <action>
tag can occur N times and every action will have a unique set of keys. I tried a couple of different solutions and options but it seems like I cannot get the class structure/mapping correct. I am hoping to get a structure that I can call like this.
using System;
using System.Configuration;
namespace ConfigurationTest
{
public class ActionsConfig : ConfigurationSection
{
[ConfigurationProperty("poolSize")]
public string PoolSize
{
get { return (string)this["poolSize"]; }
}
[ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
public ActionList Instances
{
get { return (ActionList)this[""]; }
set { this[""] = value; }
}
}
public class ActionList : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new ActionConfig();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ActionConfig)element).Name;
}
}
public class ActionConfig : ConfigurationSection
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
}
[ConfigurationProperty("impl")]
public string Impl
{
get { return (string)this["impl"]; }
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public NameValueConfigurationCollection Settings
{
get
{
return (NameValueConfigurationCollection)base[""];
}
}
}
public class Program
{
static void Main(string[] args)
{
ActionsConfig ac = ConfigurationManager.GetSection("actions") as ActionsConfig;
Console.WriteLine(ac.PoolSize);
ActionConfig nameValueSection = ac.CurrentConfiguration.GetSection("action") as ActionConfig;
NameValueConfigurationCollection settings = nameValueSection.Settings;
foreach (var key in settings.AllKeys)
{
Console.WriteLine(settings[key].Name + ": " + settings[key].Value);
}
}
}
}
Exception trace is below.
System.Configuration.ConfigurationErrorsException was unhandled
Message=Unrecognized element 'action'. (UnitTestExperiments.vshost.exe.Config line 8)
Source=System.Configuration
BareMessage=Unrecognized element 'action'.
Filename=UnitTestExperiments.vshost.exe.Config
Line=8
StackTrace:
at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)
at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at ConfigurationTest.Program.Main(String[] args) in C:\Users\me\Documents\Visual Studio 2010\Projects\UnitTestExperiments\Program.cs:line 63
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Take a look at use Custom Configuration Settings. This has a very good example.
Updates
Custom ADD sections take a look at the example Custom ConfigurationSections in .NET 2.0 .config Files