Generic Custom Configuration Handler in .Net

Sometimes we find App.config inadequate in addressing our problems and need to have a generic solution in creating strongly typed configuration files. Depending on the requirements, this can be achieved in multiple ways. In this article, I will illustrate one simple way of creating a type-safe configuration handler which can be easily adapted to more complex scenarios.

Suppose that the problem at hand is to create a handler that can access a configuration xml file via Property1 and Property2:

<?xml version="1.0" encoding="utf-8"?>

<Configurations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <Entry Property1="Test1" Property2="Test2" />

</Configurations>

We could start by building two .Net classes which could be serialized into the above format:

     [Serializable()]

    public class ConfigNode

    {

        private string _property1 = string.Empty;

        private string _property2 = string.Empty;

 

        [System.Xml.Serialization.XmlAttribute("Property1")]

        public string Property1

        {

            get { return _property1; }

            set { _property1 = value; }

        }

 

        [System.Xml.Serialization.XmlAttribute("Property2")]

        public string Property2

        {

            get { return _property2; }

            set { _property2 = value; }

        }

 

        public ConfigNode(string property1, string property2)

        {

            _property1 = property1;

            _property2 = property2;

        }

 

        public ConfigNode()

        {

        }

    }

The first class we built above (in C#) corresponds to the <Entry> element.

     [Serializable()]

    [System.Xml.Serialization.XmlRoot("Configurations")]

    public class ConfigElement

    {

        private ConfigNode _node = null;

 

        [System.Xml.Serialization.XmlElement("Entry")]

        public ConfigNode Node

        {

            get { return _node; }

            set { _node = value; }

        }

 

        public ConfigElement(ConfigNode node)

        {

            _node = node;

        }

 

        public ConfigElement()

        {

        }

    }

And the second class ConfigElement corresponds to the whole document. Note that it is easy to accommodate multiple <Entry> elements by using an ArrayList of ConfigNode’s.

Next, we need to build a class that provides functionalities to read and write to the property xml file:

     public class XMLPropertyHandler

    {

        public void SetXmlProperties(Type objType, string fileName, object settings)

        {

            XmlSerializer serializer = new XmlSerializer(objType);

            XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8);

            writer.Indentation = 4;

            writer.Formatting = Formatting.Indented;

            serializer.Serialize(writer, settings);

            writer.Close();      

        }

 

        public object GetXmlProperties(Type objType, string fileName)

        {

            XmlSerializer serializer = new XmlSerializer(objType);

            XmlTextReader reader = new XmlTextReader(fileName);

            object obj = serializer.Deserialize(reader);

 

            return obj;

        }

    }

Finally, the following testing code shows how this handler class can be used:

 

    class Program

    {

        public void SetProperties()

        {

            ConfigElement element = new ConfigElement(new ConfigNode("Test1", "Test2"));

 

            XMLPropertyHandler handler = new XMLPropertyHandler();

            handler.SetXmlProperties(typeof(ConfigElement), "test.xml", element);

        }

 

        public void GetProperties()

        {

            XMLPropertyHandler handler = new XMLPropertyHandler();

            ConfigElement element = handler.GetXmlProperties(typeof(ConfigElement), "test.xml") as ConfigElement;

        }

 

        static void Main(string[] args)

        {

            Program p = new Program();

            p.SetProperties();

            p.GetProperties();

        }

    }

The main benefit of the approach discussed here is that the handler class provides a generic way of accessing attributes driven property files. As long as the entries are defined via attributes, the handler class remains the same. This makes it easy for a generic way of handling multiple configuration files.

Be Sociable, Share!

Leave a Reply