I want to inject a Microsoft.Extensions.Logging
logger into the constructor of a class using the Unity DI container:
using Microsoft.Extensions.Logging;
namespace LoggingExample
{
public class MyClass
{
private readonly ILogger<MyClass> _logger;
public MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
public void DoSomething()
{
_logger.LogInformation("Doing something.");
}
}
}
This Stackoverflow answer suggests it's a bad idea to inject ILogger<T>
as it's too specific. Instead, the answer suggests injecting the non-generic base type, ILogger
, which is simpler, easier to test and less error prone (from copy and paste errors mainly, I would guess).
In the class above we'd want to change the data type of the constructor parameter:
public MyClass(ILogger logger)
{
_logger = logger;
}
Then we'd need some way of resolving ILogger
into Logger<MyClass>
for this class, or Logger<T>
in the more general case for any class, where T
represents the class being injected into.
This is done in that Stackoverflow answer using the Simple Injector DI container and conditional registration:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
_ => true);
Is conditional registration possible in Unity? is there any other way Unity could recognize the class it's injecting ILogger
into and resolve the reference to inject a Logger<T>
object (where T
is the class being injected into)?
You can define a name for each ILogger
instance and use the [Dependency]
attribute to specify which one you want. Example:
public static class Constants
{
public const string LOGGER_MYCLASS_UNITY_KEY = "ILogger<MyClass>";
}
In your Unity registration:
IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, Logger<MyClass>>(Constants.LOGGER_MYCLASS_UNITY_KEY,
new ContainerControllerLifetimeManager());
In the constructor of the class that needs the logger:
public class MyClass
{
private readonly ILogger<MyClass> _logger;
public MyClass([Dependency(Constants.LOGGER_MYCLASS_UNITY_KEY)] ILogger logger)
{
_logger = (ILogger<MyClass>)logger;
}
}
HTH.