user6495763 user6495763 - 3 months ago 18
C# Question

c# static class that uses another class

I have a logger API that I can use to log to text.
The logger has some properties that I can use to record envent types (Info, Err, etc...), source app (app1, app2, etc...) and mesg text.

The syntax is simple and is working OK:

Logger log = new Logger();
log.Write("Information", "SourceApplication", "Test text to log");


Now I m thinking creating 2 static classes, one for "General Purpose Logging" and other for "Debug Logging". The goal is to avoid to create a new instance of the logger object for each module utilization. Each class should be able to use these objects without instantiation (the static classes should take care of that automatically).

"Debug Logging" - Can be used by any project inside the solution and should be a singleton.
The Caller Code to use should be:

LoggerDebug.Write("Debug", "Debugger", "Test text to log");


General Purpose Logging - To be used by all project modules but after each utilization the static class should dispose the Logger Object
The Caller Code to use should be:

LoggerDebug.Write("Information", "App1", "Test text to log");


I tried to start with the "Debug Logging" static class, I read (http://csharpindepth.com/Articles/General/Singleton.aspx) but I`m not sure if this is the correct way to do this...
Can you give me some suggestions?

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
public sealed class LoggerDebug
{
private static LoggerDebug instance = null;
private static readonly object padlock = new object();
private static Logger log;

static LoggerDebug Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new LoggerDebug();
}
return instance;
}
}
}

public LoggerDebug()
{
log = new Logger();
}

public static void Write(String EventType, string appSource, string text)
{
log.Write(EventType, appSource, string.Format("Test {0}", text));
}
}
}


The caller code appears like this:

LoggerDebug.Write("Information", "App1", "Test text to log");


When I try to run the application it crashes with:


An unhandled exception of type 'System.NullReferenceException'
occurred in Common.dll Additional information: Object reference not
set to an instance of an object.


That said the ctor is not instantiating the
log = new Logger();


So I can correct this problem with:

private static Logger log = new Logger();


And commenting the ctor code

public LoggerDebug()
{
//log = new Logger();
}


But I m confused, not sure if this is the correct way to do this, How to do this correctly?

Any examples that I can use?

Answer

Here is the updated code. Make the whole thing static as there are no instance members/methods. See the comments in the code.

On a side note I strongly recommend you do not do this for anything other than a learning experience. Use existing frameworks like Log4Net or NLog which are highly configurable and widely tested.

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
    // changed sealed to static as there are no instances
    public static class LoggerDebug
    {
        // removed lock object 
        private static Logger log;

        // added static constructor
        static LoggerDebug(){
            log = new Logger();
        }

        // no need for lock due to static constructor
        // removed Instance
        // removed instance constructor

        public static void Write(String EventType, string appSource, string text)
        {
            log.Write(EventType, appSource, string.Format("Test {0}", text));
        }
    }
}

Alternatively you can use a Singleton pattern but you need at least 1 instance level (non static) member for it to be of use.

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
    // changed sealed to static as there are no instances
    public sealed class LoggerDebug
    {
        // removed lock object 
        private static Logger log;

        // added static constructor
        static LoggerDebug(){
            log = new Logger();
            _logger = new LoggerDebug();
        }

        // singleton that is created only once
        private static LoggerDebug _logger;
        public static LoggerDebug Logger{
            get{return _logger;}
        }

        // removed static keyword
        public void Write(String EventType, string appSource, string text)
        {
            log.Write(EventType, appSource, string.Format("Test {0}", text));
        }
    }
}

You can also initialize your static fields inline like you did in your example. Ideally you would never want to initialize static fields in instance level members because of possible race conditions and the expense of having to write a check that executes for every instance, it is not efficient and makes for brittle code.