Resolve generic Microsoft.Extensions.Logging.ILogger<T> with Unity - get InvalidCastException

The easiest way I have found is to register a factory and reflect their extension method to do it and get the right response type. This example also expects that you have registered an ILoggerFactory.

_container = new UnityContainer();
_container.RegisterInstance<ILoggerFactory>(new LoggerFactory().AddLog4Net(), new ContainerControlledLifetimeManager());
_container.RegisterFactory(typeof(ILogger<>), null, (c, t, n) =>
        {
            var factory = c.Resolve<ILoggerFactory>();
            var genericType = t.GetGenericArguments().First();
            var mi = typeof(Microsoft.Extensions.Logging.LoggerFactoryExtensions).GetMethods().Single(m => m.Name == "CreateLogger" && m.IsGenericMethodDefinition);
            var gi = mi.MakeGenericMethod(t.GetGenericArguments().First());
            return gi.Invoke(null, new[] { factory });
        });

Since there's already a Logger<T> implementation that takes an ILoggerFactory as a dependency you can just do

container.RegisterType<ILoggerFactory, MyLoggerFactory>();
container.RegisterType(typeof(ILogger<>), typeof(Logger<>));
container.Resolve<ILogger<MyClass>>();


I resolved this with the help of MakeGenericMethod and a helper method:

private static ILogger<T> CreateLogger<T>(ILoggerFactory factory)
{
    return new Logger<T>(factory);
}

And the final code (without reflection caching etc):

// Arrange
IUnityContainer container = new UnityContainer();

var logfactory = new LoggerFactory();

var provider = new Serilog.Extensions.Logging.SerilogLoggerProvider();
logfactory.AddProvider(provider);

container.RegisterType(typeof(Microsoft.Extensions.Logging.ILogger<>),
    new InjectionFactory((ctr, type, name) =>
    {
        var loggerType = type.GetGenericArguments()[0];

        var myType = this.GetType();

        var createLoggerMethod1 = myType.GetMethod(nameof(CreateLogger),BindingFlags.Static | BindingFlags.NonPublic);

        var createLoggerMethod = createLoggerMethod1.MakeGenericMethod(loggerType);

        var logger = createLoggerMethod.Invoke(this, new object[] {logfactory});

        return logger;
    }));

container.RegisterType<MyClass, MyClass>();

// Assert
container.Resolve<MyClass>();