Silverlight / Castle Windsor – how to use a logging framework properly

Print Content | More

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).



Castle windsor, Logging, Silverlight

2 comments

Related Post

  1. #1 da Andrea Balducci - Wednesday March 2010 alle 11:12

    Just set the default logger instance to NullLogger.Instance

  2. #2 da Alessandro Giorgetti - Wednesday March 2010 alle 12:04

    Ofc you're right I just forgot to mention that possibility in the original post. I edited and added it. Thx for pointing it out so fast.

All fields are required and you must provide valid data in order to be able to comment on this post.


(will not be published)
(es: http://www.mysite.com)


  1. #1 da http://topsy.com/trackback?url=http://www.primordialcode.com/blog/post/silverlight-castle-windsor-logging-framework-properly

    Twitter Trackbacks for www.primordialcode.com - Silverlight / Castle Windsor – how to use a logging framework properly [primordialcode.com] on Topsy.com