3
votes

I have a log4net wrapper class... But i need to instantiate everytime when i call it from other classes to log the error. I need to overcome that.. Recently i came across the singleton class which is not familiar to me.. Hence I need help in converting my current wrapper class to the singleton class..

I am posting my log4net wrapper class which i am currently using below..

using System;
using System.Data;
using System.Configuration;
using Asset.Business;

/// <summary>
/// Summary description for Logger
/// </summary>

namespace AssetsDataService
{
    public class ErrorLogger
    {
        private static log4net.ILog logger = null;
        public ErrorLogger()
        {
            if (logger == null)
            {

                string logConfigPath = ConfigSettings.GetEnvConfigValue("LogConfigXMLPath"); // this contains the path of the xml

                System.IO.FileInfo fileInfo = new System.IO.FileInfo(logConfigPath);
                log4net.Config.DOMConfigurator.Configure(fileInfo);

                string loggerName = ConfigurationManager.AppSettings.Get("ErrorLoggerName"); // this contains the name of the logger class

                logger = log4net.LogManager.GetLogger(loggerName);
            }

        }

        public void Fatal(Object message)
        {
            logger.Fatal(message);
        }

        public void Fatal(Object message, Exception exception)
        {
            logger.Fatal(message, exception);
        }

        public void Error(Object message)
        {
            logger.Error(message);
        }

        public void Error(Object message, Exception exception)
        {
            logger.Error(message, exception);

        }

        public void Debug(Object message)
        {

            logger.Debug(message);
        }

        public void Info(Object message)
        {
            logger.Info(message);
        }
    }
}

And this is the code which i tried to make my wrapper class singleton:

using System;
using System.Data;
using System.Configuration;
using Asset.Business;

/// <summary>
/// Summary description for Logger
/// </summary>

namespace AssetsDataService
{
    public class ErrorLogger
    {

        private static volatile ErrorLogger instance;
        private static object syncRoot = new Object();
         private static log4net.ILog logger = null;

        private ErrorLogger()
        {
            if (logger == null)
            {

                string logConfigPath = ConfigSettings.GetEnvConfigValue("LogConfigXMLPath"); // this contains the path of the xml

                System.IO.FileInfo fileInfo = new System.IO.FileInfo(logConfigPath);
                log4net.Config.DOMConfigurator.Configure(fileInfo);

                string loggerName = ConfigurationManager.AppSettings.Get("ErrorLoggerName"); // this contains the name of the logger class

                logger = log4net.LogManager.GetLogger(loggerName);
            }

        }

        public static ErrorLogger Instance()
        {

            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                        instance = new ErrorLogger();
                }
            }

            return instance;
         }


        public void Fatal(Object message)
        {
            logger.Fatal(message);
        }

        public void Fatal(Object message, Exception exception)
        {
            logger.Fatal(message, exception);
        }

        public void Error(Object message)
        {
            logger.Error(message);
        }

        public void Error(Object message, Exception exception)
        {
            logger.Error(message, exception);

        }

        public void Debug(Object message)
        {

            logger.Debug(message);
        }

        public void Info(Object message)
        {
            logger.Info(message);
        }
    }
}

Is this class a correct singleton class and will it handle logging correctly?

How would i call the logger ErrorLogger class to log an error or info etc..

By using my normal class i used to call it as

ErrorLogger log = new ErrorLogger();
log.Error(string.Concat("Exception Occurred :" + ex.Message, "/n", ex.StackTrace));

How can i log if i use the singleton class??

1
In general I would consider implementing IoC/DI. Unity, Ninject, Autofac are quite popular and you should be able to find plenty of info how to use any of thoseRamunas
@Ramunas ya i have read that... My doubt is how would i call the logger class in other classes if i make it as singleton classXavier
If Logger is singleton then it would be ErrorLogger.Instance.Debug("test")Ramunas
@Ramunas I have edited my question.. Please check the edit and suggest me will that work..Xavier

1 Answers

2
votes

This is a correct implementation of the singleton pattern. You can call the methods to log with the following statement:

ErrorLogger.Instance.Fatal(Exception);

Please notice that this implementation isn't thread safe, this means if you use several threads to log different messages with this logger you might get some unexpected exceptions. You can fix this quick and dirty by surrounding all your public methods with a lock.

For example:

private object _lock = new object();

public void Error(Object message)
{
    lock(_lock){
        logger.Error(message);
    }
}

also make sure you use the same lock object on every public method inside the class.