Skip to content

NLog GetCurrentClassLogger and Microsoft ILogger

Rolf Kristensen edited this page Sep 17, 2021 · 29 revisions

Microsoft ILogger Injection

Where NLog recommends having Logger as static class member, then Microsoft ILogger should be injected as input-parameter for the class-constructor:

public class MyClass
{
     private readonly ILogger Logger;

     public MyClass(ILogger<MyClass> logger)
     {
         Logger = logger;
     }
}

NLog GetCurrentClassLogger finds its Logger-Name using reflection tricks, but the generic Microsoft ILogger<MyClass> extracts the Logger-Name from the generic-type. The Microsoft Dependency Injection has a small memory allocation overhead, as it will always allocate a new class-object for every ILogger<MyClass>-parameter.

This introduces some extra noise for all class contructors. But it also makes it possible to have multiple Host-applications within the same process.

How to get ILogger with dynamic Logger name ?

If a class must generate output to multiple logger-objects, then NLog provides LogManager.GetLogger("ExtraLog"). But one have to do this to make it work with Microsoft ILogger:

public class MyClass
{
     private readonly ILogger Logger;
     private readonly ILogger ExtraLogger;

     public MyClass(ILogger<MyClass> logger, ILoggerFactory loggerFactory)
     {
         Logger = logger;
         ExtraLogger = loggerFactory.CreateLogger("ExtraLog");
     }
}

How to create class instance without ILogger ?

.NET Core 2 introduced the NullLogger and NullLoggerFactory so one can do this:

public class MyClass
{
     private readonly ILogger Logger;

     public MyClass(ILogger<MyClass> logger = null)
     {
         Logger = logger ?? NullLogger.Instance;
     }
}

This can be useful in unit-testing scenarios, or for utility-classes where logging output is not always necessary.

How to create local ILogger for class instance ?

This can be useful during application startup logging before the dependency injection system is fully initialized

var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger("StartupLogger");
logger.LogInformation("Starting...");

This can also be used for unit-testing scenarios, as each test-scenario can have their own local LoggerFactory.