What is a singleton class? Well basically it's a class that can only be instantiated ONE TIME within the confines of an applications space. Why is this useful? Well, it's a great place for creating and managing single point code logging functions or holding global data that requires a bit to retrieve.
For example, I wrote a program for a user that read data from an Access database. When the program started, I instantiate a singleton and run a query to get the version of the data (within a table / row). This value is stored in the singleton upon startup. Now, when the dozens of custom reports are run, this information is printed on the header by simply referencing the singleton variable as opposed to running this query every time that value is needed.
In the example below, I am going to create a singleton class that contains one of my most used functions, WriteToLog.
First, lets create a singleton class in Visual Studio by right clicking the project name in the "Solution Explorer" pane and selecting "Add New Item." Select "Class" and type in a name for your new singleton class (example: LocalEnv). Enter this in the source code window:
1: using System;
2: public class LocalEnv
3: {
4: private static LocalEnv instance = null;
5: private LocalEnv() {}
6: public static LocalEnv Instance
7: {
8: get
9: {
10: if (instance == null)
11: {
12: instance = new LocalEnv();
13: }
14: return instance;
15: }
16: }
17: }
Notice how the constructor is private? This means that the class can only be instantiated internally by using the "new" command and referencing it through the instance variable. If an instance of this class already exists in memory, it will simply return the already instantiated instance. If not, it creates a new instance of the class. Be sure to note the differences in the Instance variable and the instance variable (upper and lowercase 'i' versions). They are two seperate things.
Next, we'll need to create a function within our LocalEnv class that will write a message to a log file. In this example, I will assume that this is a website and that we want to write all of our logs to a subdirectory under the App_Data directory (or wherever you want) and that the log filename will be the date the event occurred.
1: public void WriteToLog(string sBaseDir, string sText)
2: {
3: string sLogFilename = sBaseDir + "/MyWebLogs/" +
4: string.Format("{0:d}{1:d2}{2:d2}.log", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
5: StreamWriter myStream = null;
6: sText = DateTime.Now.ToShortDateString() + " "+DateTime.Now.ToShortTimeString() + ": " + sText;
7: using (myStream = new StreamWriter(sLogFilename, true))
8: {
9: myStream.WriteLine(sText);
10: }
11: }
Now, in our .aspx file, we can write any message to the generic text log as follows:
1: LocalEnv.Instance().WriteToLog(Request.MapPath("~/App_Data"), "A new user was added");
Whenever we call the function, it will write a single line to the log file in the directory we specify. It will write all log entries into a single file for the day. The result in our log file file (example: c:\inetpub\wwwroot\App_Data\MyWebLogs\20100114.log) will look like:
01/14/2010 17:54:14: A new user was added