This post has been migrated from www.experimentsincode.com, we apologise if some of the images or content is missing

As part of you  Sitecore project you might use Castle Windsor to perform dependency injection, one of the great things that Castle Windsor allows  us to do is create a very simple method for injecting a Logger into you classes. Typically most people will try to use Log4Net as described here because Log4Net comes shipped with Sitecore. However you will quickly find that for some reason it doesn't work. This doesn't work because Sitecore have created their own copy of Log4Net which is pretty much the same as the original but all the types live in a different assembly. This means that when the Castle Log4Net Facility tries to inject the loggers it can't because the types are different. Look at the two interface definitions for ILog, they live in the same namespace but different assemblies:
log4net.ILog, log4net
log4net.ILog, Sitecore.Logging
To get around this type problem we can create our own Castle Facility to inject the Sitecore version of Log4Net. The facility itself is very simple:
     public class LoggingFacility : AbstractFacility, ISubDependencyResolver
    {
        protected override void Init()
        {
            this.Kernel.Resolver.AddSubResolver(this);
        }

        #region ISubDependencyResolver Members

        public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency)
        {
            return dependency.TargetType == typeof(ILog);
        }

        public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency)
        {

                    return  global::Sitecore.Diagnostics.LoggerFactory.GetLogger(model.Implementation);

        }
        #endregion
    }
You can see here we create a facility that injects a sub-resolver which is itself, the sub-resolver is called whenever castle finds a property that accepts log4net.ILog, Sitecore.Logging. It is important that your project only references the Sitecore.Logging assembly and not the log4net assembly. One other class to create is a null logger that you can assign to you logging property in your classes (see Null Object Pattern). You should create this class from the log4net.ILog, Sitecore.Logging interface. Once you have you classes you need to configure Castle Windsor to pick up your new facility:
    <facility id="loggingfacility" type="Demo.LoggingFacility,  Demo.Foundation" />
You can then use the log4net.ILog, Sitecore.Logging interface in your classes for logging:
       ILog _logger = new NullLogger();
       public ILog Logger
       {
           get
           {
               if (_logger == null) _logger = new NullLogger();
               return _logger;
           }
           set
           {
               _logger = value;
           }
       }
Again remember that the ILog interface must be the one declared in the Sitecore.Logging assembly and not the one in the log4net assembly.
comments powered by Disqus