How to read an object from app.config?

randomraccoon picture randomraccoon · Feb 27, 2016 · Viewed 8.6k times · Source

This is not a new question, but I've been researching this for two days and all the answers I can find are outdated or unhelpful. What I want to do is put an object into App.config and then load it when the program starts.

I've got a basic class called "Person" with three autoproperties: (string) FirstName, (string) LastName, and (int) Age. Here's my App.config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup>
  <configSections>
    <sectionGroup name="People">
      <section 
        name="Person" 
        type="Person.Person"
      />
    </sectionGroup>
  </configSections>
  <People>
    <Person>
      <Person type="Person.Person, Person">
        <FirstName>Jimmy</FirstName>
        <LastName>Dean</LastName>
        <Age>2</Age>
      </Person>
    </Person>
  </People>
</configuration>

And here is my program:

using System;
using System.Configuration;

namespace AppConfigTest
{
    class AppConfigTester
    {
        public static void Main(string[] args)
        {
            var guy = (Person.Person) ConfigurationManager.GetSection("People/Person");
            Console.WriteLine(guy.FirstName);
            Console.WriteLine(guy.LastName);
            Console.WriteLine(guy.Age);
        }
    }
}

At the moment it crashes with a ConfigurationErrorsException. Any help would be very appreciated. It's boggling my mind that this is so difficult, when App.config is supposed to make doing this sort of thing easier.

Answer

JimG picture JimG · Feb 27, 2016

Given a Person POCO class:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

First you need to create a class that inherits System.Configuration.ConfigurationElement like this:

public class PersonElement : ConfigurationElement
{
    public string InnerText { get; private set; }

    protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
    {
        InnerText = reader.ReadElementContentAsString();
    }
}

This is needed so you can have config elements like <FirstName>Jimmy</FirstName> with inner text.

Next you need a class that inherits System.Configuration.ConfigurationSection like this:

public class PersonSection : ConfigurationSection
{
    [ConfigurationProperty("FirstName")]
    public PersonElement FirstName
    {
        get { return this["FirstName"] as PersonElement; }
        set { this["FirstName"] = value; }
    }

    [ConfigurationProperty("LastName")]
    public PersonElement LastName
    {
        get { return this["LastName"] as PersonElement; }
        set { this["LastName"] = value; }
    }

    [ConfigurationProperty("Age")]
    public PersonElement Age
    {
        get { return this["Age"] as PersonElement; }
        set { this["Age"] = value; }
    }

    public Person CreatePersonFromConfig()
    {
        return new Person()
        {
            FirstName = this.FirstName.InnerText,
            LastName = this.LastName.InnerText,
            Age = Convert.ToInt32(this.Age.InnerText)
        };
    }
}

Your app.config should look like this:

<configuration>
    <configSections>
        <sectionGroup name="People">
            <section name="Person" type="Example.PersonSection, Example" />
        </sectionGroup>
    </configSections>
    <People>
        <Person>
            <FirstName>Jimmy</FirstName>
            <LastName>Dean</LastName>
            <Age>2</Age>
        </Person>
    </People>
</configuration>

Finally somewhere in your code do this:

PersonSection config = (PersonSection)ConfigurationManager.GetSection("People/Person");
Person guy = config.CreatePersonFromConfig();