Search code examples
c#app-configconfigurationmanager

How to read an object from app.config?


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.


Solution

  • 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();