Quote


A good programmer is a lazy programmer, because he writes minimum code.
--Anonymous


Thursday, April 1, 2010

Singleton to Read Configuration

Friends,

When we first learned the basics of coding, we are told that simple code is the best code. We believed if for a long time, and went extra mile to make the code simpler. Then came the Design Patterns, the new excuse for making code complicated. Earlier we used two lines of code to instantiate an object, but now we are using four classes for the same purpose.

Having said that, design patterns are useless things? Not at all. Those are handy, when you need to solve a real problem in a standard way. Say, connecting with multiple databases or need to make sure only one instance of an object exists at any given point of time. The problem is design patterns are more abused than used. A DP used just to show cause the knowledge of the architect or programmer.

Recently, one of my friends came to me with a problem and together we solved it by using Singleton pattern.The scenario is like this. We are storing some application settings in an external XML file (don't ask me why we are not using web.config. There are many reasons). We need to read these settings from the XML file at the start of a cycle. These settings are used at different stages of the cycle. Also, one cycle is completed by calling different methods of different classes.

We have decided to use a Config class, to read from XML file. In the constructor of this class, we will write code to read from XML. We will add a few properties to this class, to expose the settings in XML. We will declare this class at class level (as private) and instantiate this class at the start of a cycle. We will need to pass this class to methods of other classes, which are called during the cycle. Good, no?

But after designing it, we didn't feel it is satisfactory. Why should it be declared as private? Why should it be carried as a baggage around different classes? Isn't there a better way?

Then the idea of Singleton came to our minds. (I don't remember who thought it first). We can make the Config class a Singleton. So no need to declare it as private. No need to carry it across classes. We can call it whenever we needed and only once the constructor will be executed. So, only once the setting will be read from XML file. Cool.

So the first step would be to make a singleton class.


namespace ConfigTest
{
    public class Config
    {
        private static Config instance;

        private Config()
        {
 
        }

        public static Config Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Config();
                }
                return instance;
            }
        }
    }
}

Please note that the constructor is private.

Now add the properties to expose the settings. For brevity, let's assume there are three settings, viz ServerName, UserName and Password. See the XML file.


<Configurations>
  <configuration>
    <ServerName>MyServer<ServerName>
    <UserName>user<UserName>
    <Password>password<Password>
  <configuration>
<Configurations>


Now we need to add three properties to expose these settings.


       public string ServerName
        {
            get
            {
                return serverName;
            }
        }

        public string UserName
        {
            get
            {
                return userName;
            }
        }

        public string Password
        {
            get
            {
                return password;
            }
        }
Three private variables serverName, userName and password are declared. What we do now is add the code in constructor to read from XML.Please find below the new constructor code.


         private Config()
        {
            XElement xml = XElement.Load("Config.xml");
           
            serverName = xml.Elements("configuration").
                        First().Element("ServerName").Value;
            userName = xml.Elements("configuration").
                        First().Element("UserName").Value;
            password = xml.Elements("configuration").
                        First().Element("Password").Value;
        }


We are done with the code. It is ready to execute. Now how can we call this Config class from our main class? It is easy. The following code shows how to display the settings from a Windows form.


            MessageBox.Show(Config.Instance.ServerName);
            MessageBox.Show(Config.Instance.UserName);
            MessageBox.Show(Config.Instance.Password);


When the first message box is executed, the details will be read from the XML file. During the consecutive executions, it just displays the property values. But what if we need to re-read from XML file? For example, before the start of next cycle, we need to refresh the settings. So we have added a new method to Config class, to refresh the settings.


        public void Refresh()
        {
            instance = new Config();
        }

That's all friends. If you interested to view the class diagram of our class, here it is.


















Hope this will help some one. You can download the entire solution here.

Thanks.

No comments:

Post a Comment