Click here to Skip to main content
15,884,353 members
Articles / Programming Languages / C#

How to Implement Custom configSection with Nested Elements in C#

Rate me:
Please Sign up or sign in to vote.
3.00/5 (5 votes)
8 May 2014CPOL3 min read 51.1K   577   15   14
After completing this exercise, you should be able to implement custom configSection, with nested elements, in your application's config file.

Objective

After completing this exercise, you should be able to implement custom configSection, with nested elements, in your application’s config file.

In my previous post, How to implement custom configSection in your configuration, I have explained the details about how to implement simple single element based custom configSection in your configuration, i.e., without any nested elements.

However in many scenarios, we need to implement custom configSection having nested elements. It is very useful in cases where you need to store some limited number of configuration details or any data, and you do not want to use database for storing those configurations.

Here, I will explain the step by step process to implement custom configSection with nested elements. Like most of my posts, I have followed a practical approach rather than providing theory. Following this, you will be able to achieve the goal of the post.

Step 1

Create a new Console application named as “CustomNestedConfigSection”.

Step 2

Create a folder under this project named as “NestedConfig”.

Step 3

Add a new App.config file to the project.

Step 4

Add a new class file “EmployeesConfigSection.cs” in NestedConfig folder as below:

C#
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class EmployeesConfigSection : ConfigurationSection
    {
        //If you replace "employeeCollection" with "" then you do not need "employeeCollection" 
        //element as a wrapper node over employee nodes in config file.
        [ConfigurationProperty("employeeCollection", IsDefaultCollection = true, 
        IsKey = false, IsRequired = true)]
        public EmployeeCollection Members
        {
            get
            {
                return base["employeeCollection"] as EmployeeCollection;
            }

            set
            {
                base["employeeCollection"] = value;
            }
        }
    }
}

Step 5

Add a new class file “EmployeeCollection.cs” in NestedConfig folder as below:

C#
using System;
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class EmployeeCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new Employee();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Employee) element).Id;
        }

        protected override string ElementName
        {
            get
            {
                return "employee";
            }
        }

        protected override bool IsElementName(string elementName)
        {
            return !String.IsNullOrEmpty(elementName) && elementName == "employee";
        }

        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.BasicMap;
            }
        }

        public Employee this[int index]
        {
            get
            {
                return base.BaseGet(index) as Employee;
            }
        }

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

Step 6

Add a new class file “Employee.cs” in NestedConfig folder as below:

C#
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class Employee : ConfigurationElement
    {
        [ConfigurationProperty("id", IsKey = true)]
        public string Id { get { return (string) this["id"]; } }

        [ConfigurationProperty("personalInfo")]
        public PersonalInfo PersonalInfo
        {
            get { return (PersonalInfo)this["personalInfo"]; }
        }

        [ConfigurationProperty("homeAddress")]
        public Address HomeAddress { get { return (Address)this["homeAddress"]; } }

        [ConfigurationProperty("officeAddress")]
        public Address OfficeAddress { get { return (Address)this["officeAddress"]; } }
    }
}

Step 7

Add a new class file “PersonalInfo.cs” in NestedConfig folder as below:

C#
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class PersonalInfo : ConfigurationElement
    {
        [ConfigurationProperty("ssn", IsKey = true)]
        public string SSN { get { return (string)this["ssn"]; } set { this["ssn"] = value; } }

        [ConfigurationProperty("height")]
        public int Height { get { return (int)this["height"]; } set { this["height"] = value; } }

        [ConfigurationProperty("weight")]
        public int Weight { get { return (int)this["weight"]; } set { this["weight"] = value; } }
    }
}

Step 8

Add a new class file “Address.cs” in NestedConfig folder as below:

C#
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class Address : ConfigurationElement 
    {
        [ConfigurationProperty("pin")]
        public string PinCode { get { return (string) this["pin"]; } }

        [ConfigurationProperty("city")]
        public string City { get { return (string)this["city"]; } }

        [ConfigurationProperty("state")]
        public string State { get { return (string)this["state"]; } }
    }
}

Step 9

Modify “App.config” file in your application as below:

C#
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="employeeCollectionSection" 
    type="CustomNestedConfigSections.NestedConfig.EmployeesConfigSection, 
    CustomNestedConfigSections"/>
  </configSections> 
  <employeeCollectionSection>
    <employeeCollection>
      <employee id="1">
        <personalInfo ssn="3243423" height="342"  weight="78" />
        <homeAddress pin="411001" city="Pune" state="Maharashtra"/>
        <officeAddress pin="844101" city="Shahdra" state="Delhi"/>
      </employee>
      <employee id="2">
        <personalInfo ssn="7435623" height="342" weight="62" />
        <homeAddress pin="411002" city="Pimpri" state="Maharashtra"/>
        <officeAddress pin="874785" city="Mangolpuri" state="Haryana"/>
      </employee>
    </employeeCollection>
  </employeeCollectionSection>
</configuration>

Step 10

Modify “Program.cs” file in your application as below:

C#
using System;
using System.Configuration;
using CustomNestedConfigSections.NestedConfig;

namespace CustomNestedConfigSections
{
    class Program
    {
        static void Main(string[] args)
        {
            var employee1 = GetEmployee("1");
            Console.WriteLine("\n\nDetails of employee with id : 1");
            Console.WriteLine("Personal Info: SSN - {0} Height - {1}inch Weight - {2}Kg", 
            employee1.PersonalInfo.SSN, employee1.PersonalInfo.Height,employee1.PersonalInfo.Weight);
            Console.WriteLine("Home Address : {0} {1} {2}", employee1.HomeAddress.City, 
            employee1.HomeAddress.State, employee1.HomeAddress.PinCode);
            Console.WriteLine("Office Address : {0} {1} {2}", employee1.OfficeAddress.City, 
            employee1.OfficeAddress.State, employee1.OfficeAddress.PinCode);

            Console.ReadKey();
        }

        public static Employee GetEmployee(string employeeId)
        {
            var employeesConfigSection = ConfigurationManager.GetSection
            ("employeeCollectionSection") as EmployeesConfigSection;

            if (employeesConfigSection == null || 
            employeesConfigSection.Members == null || employeesConfigSection.Members.Count < 1)
                return null;

            return employeesConfigSection.Members[employeeId];
        }
    }
}

Step 11

Run your console application. Do not forget to add reference of “System.Configuration” in your console application project. I hope you will not get any error while running the application. However if you get one, you would be able to fix it.

Now I will explain the terms or points which have not been covered above.

  • For each element/node in your config, you need to create a corresponding class which derives from “ConfigurationElement”.
  • To define an attribute for any element/node, you need to create a public property with “ConfigurationProperty” attribute. For example, if you want to create an attribute named “city” for an element, then define a property like:
    C#
    [ConfigurationProperty("city")]
    public string City { get { return (string)this["city"]; } }
  • You define the name of element/node/attribute inside “ConfigurationProperty” attribute.
  • If you want more than one child node under an element or node, then you need to create a new class for that collection which should be derived from “ConfigurationElementCollection”. Here, you also define name of the element which represents your collection as I have created “employee" for employee collection.
  • To create root element/node for your configSection, you must create a class which derives from “ConfigurationSection”. To create simplest configSection, you need a single class derived from “ConfigurationSection” having properties, with ConfigurationProperty attribute, corresponding to required attributes.
  • If you do not want wrapper element/node for your collection, then replace ConfigurationProperty name with blank. For example, if you do not want “employeeCollection” element/node in your config file, then replace ConfigurationProperty name with blank from EmployeesConfigSection as below:
    C#
    //If you replace "employeeCollection" with "" 
    //then you do not need "employeeCollection" 
    //element as a wrapper node over employee nodes in config file.
    [ConfigurationProperty("", IsDefaultCollection = true, IsKey = false, IsRequired = true)]
    public EmployeeCollection Members
    {
        get
        {
            return base[""] as EmployeeCollection;
        }
    
        set
        {
            base[""] = value;
        }
    }

    After making the above changes, configSection in your App.config file should be modified as:

    C#
    <employeeCollectionSection>
      <employee id="1">
        <personalInfo ssn="3243423" height="342"  weight="78" />
        <homeAddress pin="411001" city="Pune" state="Maharashtra"/>
        <officeAddress pin="844101" city="Shahdra" state="Delhi"/>
      </employee>
      <employee id="2">
        <personalInfo ssn="7435623" height="342" weight="62" />
        <homeAddress pin="411002" city="Pimpri" state="Maharashtra"/>
        <officeAddress pin="874785" city="Mangolpuri" state="Haryana"/>
      </employee>
    </employeeCollectionSection>
    
  • You will have n level of nesting of elements in this way. You will have n classes for n elements you need in your configuration.
  • You can define a static class for easy manipulation of configuration values. I have defined static methods in Program class for the purpose to get employee with given id.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionMessage Closed Pin
26-Oct-21 13:43
Member 1540877826-Oct-21 13:43 
QuestionHow can I loop through the config file once it is implemented ? Pin
Member 1084298022-Sep-21 16:15
Member 1084298022-Sep-21 16:15 
QuestionStep 1: Create a new Console application named as "CustomNestedConfigSections" (not "CustomNestedConfigSection") Pin
Member 330633710-Jun-16 5:29
Member 330633710-Jun-16 5:29 
AnswerRe: Step 1: Create a new Console application named as "CustomNestedConfigSections" (not "CustomNestedConfigSection") Pin
Adarsh Chaurasia - Passionate Trainer21-Jun-16 1:40
professionalAdarsh Chaurasia - Passionate Trainer21-Jun-16 1:40 
QuestionArrgh Pin
steveski743-Aug-15 2:28
steveski743-Aug-15 2:28 
AnswerRe: Arrgh Pin
Adarsh Chaurasia - Passionate Trainer4-Aug-15 3:01
professionalAdarsh Chaurasia - Passionate Trainer4-Aug-15 3:01 
QuestionMultiple items in the nested element Pin
kitforbes16-Jun-15 10:26
kitforbes16-Jun-15 10:26 
QuestionNested Configuration Pin
Rajaraman Soundar29-Sep-14 12:42
Rajaraman Soundar29-Sep-14 12:42 
AnswerRe: Nested Configuration Pin
Adarsh Chaurasia - Passionate Trainer29-Sep-14 21:44
professionalAdarsh Chaurasia - Passionate Trainer29-Sep-14 21:44 
QuestionNested Configuration Pin
Rajaraman Soundar29-Sep-14 12:35
Rajaraman Soundar29-Sep-14 12:35 
GeneralMy vote of 5 Pin
abeethadesilva1-Aug-14 1:53
abeethadesilva1-Aug-14 1:53 
QuestionMembershipElement ? Pin
Member 30687318-May-14 2:04
Member 30687318-May-14 2:04 
AnswerRe: MembershipElement ? Pin
Adarsh Chaurasia - Passionate Trainer8-May-14 3:28
professionalAdarsh Chaurasia - Passionate Trainer8-May-14 3:28 
GeneralRe: MembershipElement ? Pin
Member 30687318-May-14 22:23
Member 30687318-May-14 22:23 
GeneralRe: MembershipElement ? Pin
Adarsh Chaurasia - Passionate Trainer9-May-14 4:42
professionalAdarsh Chaurasia - Passionate Trainer9-May-14 4:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.