I'd like to write a logger that can be easily appended to any class in my current project. For development, it will be convenient to log messages to the console, whereas in the final release I'd like to log to a file or something. One should be able to change the behavior by editing just a few lines of code, or ideally a settings file.
What I have so far is this class structure:
public interface ILogger {
void LogMessage(String message);
// ... other logging functions (exceptions, time etc.) don't matter here
};
public interface ILoggable { };
public static class LoggingProvider {
private static ILogger logger = ConsoleLogger.handle;
public static void LogMessage(this ILoggable obj, String message) {
logger.LogMessage(message);
}
}
public sealed class NullLogger : ILogger {
// A logger that does nothing..
};
public sealed class FileLogger : ILogger {
// A logger that writes to a file..
};
public sealed class ConsoleLogger : ILogger {
#region Console Allocation
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeConsole();
#endregion
#region Singleton implementation
private static Object cs = new Object();
private static ILogger instance = null;
private ConsoleLogger() {
AllocConsole();
}
~ConsoleLogger() {
FreeConsole();
}
public static ILogger handle {
get {
lock ( cs ) { if ( instance == null ) instance = new ConsoleLogger(); }
return instance;
}
}
#endregion
#region ILogger Member
public void LogMessage(string message) {
lock ( cs ) {
String logString = getTimeString();
logString += ( " -> \t " + message );
Console.WriteLine(logString);
}
}
#endregion
#region Helper functions
// ...
#endregion
};
Now, I can have any class I'd like to implement ILoggable
, and via the Extension Method LogingProvider.LogMessage
I can call this.LogMessage("...")
within these classes. If it was C++, I'd just use private inheritance instead.
Is this now good or bad design? Anything I can improve? Is there a way to provide classes with logging functionality without the extension method, but with similarly few changes?