Search code examples
c#.netdependency-injectionunity-container.net-framework-version

Unable to register Microsoft Logger with Unity


I have a Worker with logger and the project is throwing an error: Resolution of the dependency failed, type = "Test.IWorker", name = "(none)"

public class SimpleWorker : IWorker
{
    private readonly ILogger _logger;
    public SimpleWorker(

        ILogger<SimpleWorker> logger)
    {
        _logger = logger;
    }
}

I am using Unity 4.0.0 version and .NET 4.8.

So far, I have tried with solution that I found on StackOverflow, but unsucesfully:

_container = new UnityContainer();
var loggerFactory = new LoggerFactory();
var factoryMethod =
    typeof(LoggerFactoryExtensions).
        GetMethods(BindingFlags.Static | BindingFlags.Public)
        .First(x => x.ContainsGenericParameters);

_container.RegisterType(typeof(ILogger<>), new InjectionFactory((c, t, s) =>
{
    var genFactoryMethod =
        factoryMethod.MakeGenericMethod(t.GetGenericArguments()[0]);
    return genFactoryMethod.Invoke(null, new object[] { loggerFactory });
}));

Also, I tried direct injection with, but it didn't work:

_container = new UnityContainer();
_container.RegisterType<ILogger<SimpleWorker>>();

edit: Now I have other issue with logger factory:

    var factory = new LoggerFactory();
    factory.AddLog4Net("log4net.config");
    container.RegisterInstance<ILoggerFactory>(factory);
    container.RegisterType(typeof(ILogger<>), typeof(Logger<>));

Then:

foreach (var item in _unityContainer.Registrations)
            {
                var named = _unityContainer.ResolveAll(item.RegisteredType);
                if (_unityContainer.IsRegistered(item.RegisteredType))
                {
                    var tmp = _unityContainer.Resolve(item.RegisteredType);
                }
            }

Above code throws error: Resolving Microsoft.Extensions.Logging.ILogger`1[TCategoryName][],(none) ---> System.InvalidOperationException: Could not execute the method because either the method itself or the containing type is not fully instantiated.


Solution

  • You're overthinking it. You just have to register the LoggerFactory and the Logger<T> implementation:

    using Microsoft.Extensions.Logging;
    using Unity;
    using Unity.Lifetime;
    
    var container = new UnityContainer();
    
    var factory = new LoggerFactory();
    container.RegisterInstance<ILoggerFactory>(factory,
        new ContainerControlledLifetimeManager());
    
    container.RegisterType(typeof(ILogger<>), typeof(Logger<>),
        new ContainerControlledLifetimeManager());
    
    container.RegisterType<IWorker, SimpleWorker>();
    
    var worker = container.Resolve<IWorker>();
    
    public interface IWorker { }
    public class SimpleWorker : IWorker
    {
        private ILogger<SimpleWorker> _logger;
        public SimpleWorker(ILogger<SimpleWorker> logger) => _logger = logger;
    }
    

    Also note that there is a Unity.Microsoft.Logging NuGet package that allows you to achieve the same:

    using Microsoft.Extensions.Logging;
    using Unity;
    using Unity.Microsoft.Logging;
    
    var container = new UnityContainer();
    
    var factory = new LoggerFactory();
    
    container.AddExtension(new LoggingExtension(factory));
    
    container.RegisterType<IWorker, SimpleWorker>();
    
    var worker = container.Resolve<IWorker>();