Saturday, October 20, 2012

C# Writing Custom Configuration Settings Section

Almost every C# application has its own Configuration Settings file also known as App.Config. If you look on your App.Config file you probably will see a list of key value pairs:
<add key="key0" value="value0" />
<add key="key1" value="value1" /> 
<add key="key2" value="value2" />
... 
But what if you need some more complex configurations? Something like this:
<MySection>
    <MySettings MyKey="John" MyValue1="Developer" MyValue2="Expert"/>
    <MySettings MyKey="Tomas" MyValue1="Developer" MyValue2="Junior"/>    
    <MySettings MyKey="Robert" MyValue1="Developer" MyValue2="Senior"/>
    <MySettings MyKey="Kurt" MyValue1="IT" MyValue2="Expert"/>
    <MySettings MyKey="Anna" MyValue1="HR" MyValue2="Senior"/>    
</MySection>
Today I'll show how to build this kind of Custom Configuration Settings in C#.

First of all, we have to define our class that will represent the whole configuration section. This class must be inherited from ConfigurationSection class. By the way, don't forget to include System.Configuration namespace. Also we need an Element class. This class will represent a single row in the section and it must be inherited from ConfigurationElement class. Third and the last class will represent the collection of our elements. Let's call it ElementCollection. This class must be inherited from ConfigurationElementCollection. Let's see the source code:

Element.cs:
public class Element : ConfigurationElement
{
    private const string ATTRIBUTE_MYKEY = "MyKey";
    private const string ATTRIBUTE_MYVALUE1 = "MyValue1";
    private const string ATTRIBUTE_MYVALUE2 = "MyValue2";
    
    [ConfigurationProperty(ATTRIBUTE_MYKEY, IsRequired = true, IsKey = true)]        
    public string MyKey
    {
        get { return (string)this[ATTRIBUTE_MYKEY]; }
        set { this[ATTRIBUTE_MYKEY] = value; }
    }

    [ConfigurationProperty(ATTRIBUTE_MYVALUE1, IsRequired = true, IsKey = false)]        
    public string MyValue1
    {
        get { return (string)this[ATTRIBUTE_MYVALUE1]; }
        set { this[ATTRIBUTE_MYVALUE1] = value; }
    }

    [ConfigurationProperty(ATTRIBUTE_MYVALUE2, IsRequired = true, IsKey = false)]        
    public string MyValue2
    {
        get { return (string)this[ATTRIBUTE_MYVALUE2]; }
        set { this[ATTRIBUTE_MYVALUE2] = value; }
    }    
}
Notice that above each property there is ConfigurationProperty attribute. Also MyKey property has IsKey attribute set to true. Let's see now ElementCollection class which represents the collection of elements:

ElementCollection.cs:
public class ElementCollection : ConfigurationElementCollection
{
    public ElementCollection()
    {
        this.AddElementName = "MySettings";
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return (element as Element).MyKey;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new Element();
    }

    public new Element this[string key]
    {
        get { return base.BaseGet(key) as Element; }
    }

    public Element this[int ind]
    {
        get { return base.BaseGet(ind) as Element; }
    }
}
I override GetElementKey method in order to determine the key attribute in the element. In our case MyKey attribute is our key in configuration element. And finally here is the code of Section class:

Section.cs:
public class Section : ConfigurationSection
{
    public const string sectionName = "MySection";

    [ConfigurationProperty("", IsDefaultCollection = true)]
    public ElementCollection MySettings
    {
        get
        {
            return this[""] as ElementCollection;
        }
    }

    public static Section GetSection()
    {
        return (Section)ConfigurationManager.GetSection(sectionName);
    }
}
We almost done. Before we can use our configuration section we must specify the name of our custom configuration section, configuration section class namespace and the assembly name where the configuration section classes are located:

<configuration>

  <configSections>
    <section name="MySection" type="CustomConfigurationSection.CustomConfig.Section, CustomConfigurationSection" />
  </configSections>
  
  <MySection>
    <MySettings MyKey="John" MyValue1="Developer" MyValue2="Expert"/>
    <MySettings MyKey="Tomas" MyValue1="Developer" MyValue2="Junior"/>
    <MySettings MyKey="Robert" MyValue1="Developer" MyValue2="Senior"/>
    <MySettings MyKey="Kurt" MyValue1="IT" MyValue2="Expert"/>
    <MySettings MyKey="Anna" MyValue1="HR" MyValue2="Senior"/>
  </MySection>

</configuration>
Here is how we access our configurations:
Console.Write(section.MySettings["John"].MyValue1);
Console.Write(section.MySettings["Anna"].MyValue2);
Download the source code (Visual Studio 2010 project).

3 comments:

  1. Configuration system failed to initialize :(

    ReplyDelete
  2. Thanks this was just what I was looking for :) helped me a lot!!

    Paul

    ReplyDelete
  3. I have been looking for a complete example like yours. Thank you for your post. It really helped me a lot !!!. Keep posting articles like these.

    ReplyDelete