In my last post I shown you how to build a simple logging framework for Silverlight applications and use it with an IoC container through ‘constructor injection’, well…in my opinion I consider that a bad programming practice. In short when using a Dependency Injection library you have two types of DI mechanism:
- Constructor Injection: DI through constructor parameters, the DI container try us the constructor that matches best all the modules it knows.
- Property Injection: DI through properties, the DI container try to resolve each property based on the modules it knows.
Usually I use constructor injection for all the modules I consider mandatory and property injection for optional modules. A logging system does not add nor carry any ‘core level’ feature to the application, it’s merely accessorial (even if extremely useful); so a good practice is to not use constructor injection to initialize it, use property injection instead.
Consider something like this:
public class TestLoggingClass
{
public TestLoggingClass()
{ }
public ILogger Logger { get; set; }
public void Operation()
{
Logger.Info("Operation started");
Logger.Debug("Operation started");
}
}In this scenario we cannot call something like: Logger.Info()…because Logger can be null (remember it’s optional now);
We have two diffirent solution to this problem:
- Register a default NullLogger instance that actually does nothing.
- Another simple solution is the to write down some extension methods that checks for Logger nullability before actually making the call, each method will be just a wrapper around your framework call:
public static class LoggingExtensions
{
#region Debug
public static void SafeDebug(this ILogger logger, string message)
{
if (logger != null)
logger.Debug(message);
}
public static void SafeDebug(this ILogger logger, string message, Exception exception)
{
if (logger != null)
logger.Debug(message, exception);
}
public static void SafeDebug(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.Debug(format, args);
}
public static void SafeDebugFormat(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.DebugFormat(format, args);
}
public static void SafeDebugFormat(this ILogger logger, Exception exception, string format, params object[] args)
{
if (logger != null)
logger.DebugFormat(exception, format, args);
}
public static void SafeDebugFormat(this ILogger logger, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.DebugFormat(formatProvider, format, args);
}
public static void SafeDebugFormat(this ILogger logger, Exception exception, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.DebugFormat(exception, formatProvider, format, args);
}
#endregion
#region Error
public static void SafeError(this ILogger logger, string message)
{
if (logger != null)
logger.Error(message);
}
public static void SafeError(this ILogger logger, string message, Exception exception)
{
if (logger != null)
logger.Error(message, exception);
}
public static void SafeError(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.Error(format, args);
}
public static void SafeErrorFormat(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.ErrorFormat(format, args);
}
public static void SafeErrorFormat(this ILogger logger, Exception exception, string format, params object[] args)
{
if (logger != null)
logger.ErrorFormat(exception, format, args);
}
public static void SafeErrorFormat(this ILogger logger, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.ErrorFormat(formatProvider, format, args);
}
public static void SafeErrorFormat(this ILogger logger, Exception exception, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.ErrorFormat(exception, formatProvider, format, args);
}
#endregion
#region Fatal
public static void SafeFatal(this ILogger logger, string message)
{
if (logger != null)
logger.Fatal(message);
}
public static void SafeFatal(this ILogger logger, string message, Exception exception)
{
if (logger != null)
logger.Fatal(message, exception);
}
public static void SafeFatal(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.Fatal(format, args);
}
public static void SafeFatalFormat(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.FatalFormat(format, args);
}
public static void SafeFatalFormat(this ILogger logger, Exception exception, string format, params object[] args)
{
if (logger != null)
logger.FatalFormat(exception, format, args);
}
public static void SafeFatalFormat(this ILogger logger, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.FatalFormat(formatProvider, format, args);
}
public static void SafeFatalFormat(this ILogger logger, Exception exception, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.FatalFormat(exception, formatProvider, format, args);
}
#endregion
#region Info
public static void SafeInfo(this ILogger logger, string message)
{
if (logger != null)
logger.Info(message);
}
public static void SafeInfo(this ILogger logger, string message, Exception exception)
{
if (logger != null)
logger.Info(message, exception);
}
public static void SafeInfo(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.Info(format, args);
}
public static void SafeInfoFormat(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.InfoFormat(format, args);
}
public static void SafeInfoFormat(this ILogger logger, Exception exception, string format, params object[] args)
{
if (logger != null)
logger.InfoFormat(exception, format, args);
}
public static void SafeInfoFormat(this ILogger logger, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.InfoFormat(formatProvider, format, args);
}
public static void SafeInfoFormat(this ILogger logger, Exception exception, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.InfoFormat(exception, formatProvider, format, args);
}
#endregion
#region Warn
public static void SafeWarn(this ILogger logger, string message)
{
if (logger != null)
logger.Warn(message);
}
public static void SafeWarn(this ILogger logger, string message, Exception exception)
{
if (logger != null)
logger.Warn(message, exception);
}
public static void SafeWarn(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.Warn(format, args);
}
public static void SafeWarnFormat(this ILogger logger, string format, params object[] args)
{
if (logger != null)
logger.WarnFormat(format, args);
}
public static void SafeWarnFormat(this ILogger logger, Exception exception, string format, params object[] args)
{
if (logger != null)
logger.WarnFormat(exception, format, args);
}
public static void SafeWarnFormat(this ILogger logger, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.WarnFormat(formatProvider, format, args);
}
public static void SafeWarnFormat(this ILogger logger, Exception exception, IFormatProvider formatProvider, string format, params object[] args)
{
if (logger != null)
logger.WarnFormat(exception, formatProvider, format, args);
}
#endregion
}This way we can have our optional logging component with an ‘elegant’ calling syntax (and we don’t pollute all our code with all those nullability checks).
Related Content
- Silverlight / Castle Windsor – implementing a simple logging framework (26/08/2015)
- Silverlight / Castle – how to use a logging framework properly (26/08/2015)
- Castle Windsor – Silverlight 4 binaries (26/08/2015)
- Castle Windsor – Silverlight 4 binaries (26/08/2015)
- Castle Windsor – Silverlight 4 binaries (26/08/2015)
- More related document (46)