title: How to get named loggers for LogManager (NLog) with Unity
body: <p>This is going to be a long winded question, but please bear with me. I am trying to create a Logging component for our applications, which can be extended to plug-in new logging frameworks (NLog, Log4Net ec). Now I know that we already have Common.Logging facade written by Ben Foster, but I wanted to try something more customized. One of the major requirements in our case, is that we need a custom mechanism of logging individual parameters/values to database using a logging framework (NLog in this case). So I have a simple logging interface:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Interface for implementing a Logger Provider.
  /// &lt;/summary&gt;
  public interface ILogger
  {
      /// &lt;summary&gt;
      /// Logs an Info level diagnostics message.
      /// &lt;/summary&gt;
      /// &lt;param name="logInfo"&gt;The Log Info object.&lt;/param&gt;
      void Info(LogInfo logInfo);
  
      /// &lt;summary&gt;
      /// Logs a Warn level diagnostics message.
      /// &lt;/summary&gt;
      /// &lt;param name="logInfo"&gt;The Log Info object.&lt;/param&gt;
      void Warn(LogInfo logInfo);
  
      /// &lt;summary&gt;
      /// Logs a Debug level diagnostics message.
      /// &lt;/summary&gt;
      /// &lt;param name="logInfo"&gt;The Log Info object.&lt;/param&gt;
      void Debug(LogInfo logInfo);
  
      /// &lt;summary&gt;
      /// Logs an Error level diagnostics message.
      /// &lt;/summary&gt;
      /// &lt;param name="logInfo"&gt;The Log Info object.&lt;/param&gt;
      void Error(LogInfo logInfo);
  
      /// &lt;summary&gt;
      /// Logs an Fatal level diagnostics message.
      /// &lt;/summary&gt;
      /// &lt;param name="logInfo"&gt;The Log Info object.&lt;/param&gt;
      void Fatal(LogInfo logInfo);
  }
  </code></pre>
  
  <p>The LogInfo object contains all the necessary logging information. I have an abstract class that implements the interface:</p>
  
  <pre><code>public abstract class NLogLoggerBase : ILogger
  {
       ....
  }
  </code></pre>
  
  <p>Which is sublcassed into:</p>
  
  <pre><code>public class NLogDatabaseLogger : NLogLoggerBase
  {
     public NLogDatabaseLogger(ILogUtility logUtility)
          : base(logUtility)
      {
          //Make sure the custom target is registered for use BEFORE using it.
          ConfigurationItemFactory.Default.Targets.RegisterDefinition("DatabaseLog", typeof(DatabaseLogTarget));
  
          //initialize the _logger
          _logger = LogManager.GetLogger("DatabaseLogger");
      }
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>public class NLogFileLogger : NLogLoggerBase
  {
     ....
  }
  </code></pre>
  
  <p>Database logger uses a custom DatabaseTarget (which inherits from TargetWithLayout in NLog) to log into the database, and ditto for File Logger. The basic settings for NLog are wired in the App.Config:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /&gt;
    &lt;/configSections&gt;
    &lt;nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          autoReload="true" throwExceptions="false" internalLogFile="C:\Temp\nlog.txt" internalLogLevel="Info"
          internalLogToConsole="false"&gt;
      &lt;targets async="true"&gt;
        &lt;target name="CustomDatabaseLog" xsi:type="DatabaseLog" /&gt;
        &lt;target name="CustomFileLog" xsi:type="File" /&gt;
      &lt;/targets&gt;
  
      &lt;rules&gt;
        &lt;logger name="DatabaseLogger" minlevel="Info" writeTo="CustomDatabaseLog" /&gt;
        &lt;logger name="FileLogger" minlevel="Info" writeTo="CustomFileLog" /&gt;
      &lt;/rules&gt;
    &lt;/nlog&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>So far so good. I have a couple of tests for each of the loggers, and they log fine to their respective targets.</p>
  
  <p>Then I wrote a Logger factory, which will return the correct implementation of ILogger interface, based on the logger type:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Provides an interface for a factory which returns a logger component.
  /// &lt;/summary&gt;
  public interface ILoggerFactory
  {
      /// &lt;summary&gt;
      /// Creates an instance of logger component based on dependency registration key.
      /// &lt;/summary&gt;
      /// &lt;param name="loggerName"&gt;The dependency registration key.&lt;/param&gt;
      /// &lt;returns&gt;An Instance of logger component.&lt;/returns&gt;
      ILogger CreateLogger(string loggerName);
  }
  </code></pre>
  
  <p>and the implementation:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Implementation of ILoggerFactory interface.
  /// &lt;/summary&gt;
  public class NLogLoggerFactory : ILoggerFactory
  {
      private readonly ILogger _nlogDatabaseLogger;
      private readonly ILogger _nlogFileLogger;
  
      public NLogLoggerFactory(ILogger nlogDatabaseLogger, ILogger nlogFileLogger)
      {
          if (nlogDatabaseLogger == null)
              throw new ArgumentNullException("nlogDatabaseLogger");
  
          if (nlogFileLogger == null)
              throw new ArgumentNullException("nlogFileLogger");
  
          _nlogDatabaseLogger = nlogDatabaseLogger;
          _nlogFileLogger = nlogFileLogger;
      }
  
      /// &lt;summary&gt;
      /// Creates an instance of logger component based on dependency registration key.
      /// &lt;/summary&gt;
      /// &lt;param name="loggerKey"&gt;The dependency registration key.&lt;/param&gt;
      /// &lt;returns&gt;An Instance of logger component.&lt;/returns&gt;
      public ILogger CreateLogger(string loggerKey)
      {
          if (loggerKey.Equals(DependencyRegistrationKeys.NLogDatabaseLoggerKey))
              return _nlogDatabaseLogger;
  
          if (loggerKey.Equals(DependencyRegistrationKeys.NLogFileLoggerKey))
              return _nlogFileLogger;
  
          throw new ArgumentException("Invalid loggerKey");
      }
  </code></pre>
  
  <p>So I go for wiring it all up with Unity. Here is quick test case I knocked up (I know it needs re-factoring, but it is for illustrative purposes):</p>
  
  <pre><code>    [Test]
      public void Test_if_logger_factory_returns_correct_implementation()
      {
          var container = new UnityContainer();
          container.RegisterType&lt;ILogUtility, NLogUtility&gt;();
          container.RegisterType&lt;ILogger, NLogDatabaseLogger&gt;(DependencyRegistrationKeys.NLogDatabaseLoggerKey);
          container.RegisterType&lt;ILogger, NLogFileLogger&gt;(DependencyRegistrationKeys.NLogFileLoggerKey);
          container.RegisterType&lt;ILoggerFactory, NLogLoggerFactory&gt;(
              new InjectionConstructor(
                  new ResolvedParameter&lt;ILogger&gt;(DependencyRegistrationKeys.NLogDatabaseLoggerKey),
                  new ResolvedParameter&lt;ILogger&gt;(DependencyRegistrationKeys.NLogFileLoggerKey)));
  
          var loggerFactory = container.Resolve&lt;ILoggerFactory&gt;();
          Assert.IsAssignableFrom&lt;NLogLoggerFactory&gt;(loggerFactory);
  
          var logger = loggerFactory.CreateLogger(DependencyRegistrationKeys.NLogDatabaseLoggerKey);
          Assert.IsNotNull(logger);
          Assert.IsAssignableFrom&lt;NLogDatabaseLogger&gt;(logger);
      }
  </code></pre>
  
  <p>All is fine until I hit the line:</p>
  
  <pre><code>var loggerFactory = container.Resolve&lt;ILoggerFactory&gt;();
  </code></pre>
  
  <p>This seems to hit the constructor of NLogDatabaseLogger as expected, and blows up on this line with an exception:</p>
  
  <pre><code>//initialize the _logger
  _logger = LogManager.GetLogger("DatabaseLogger");
  </code></pre>
  
  <p>Exception:</p>
  
  <pre><code>Required parameter 'FileName' on 'File Target[CustomFileLog_wrapped]' was not specified.
  </code></pre>
  
  <p>My guess is that Unity is struggling with getting NLog, to get a named logger instance. Has anyone encountered this before? Is there any way around this? I have spent the whole morning banging my head about this, but no dice. Any help would be really appreciated!</p>