1

I have a class like so:

public class LoggedFoo
{
    private readonly ILog _logger;

    public LoggedFoo(ILog logger)
    {
        this._logger = logger;
    }

    public DoStuff()
    {
        this._logger.Info(i => i("Doing stuff..."));
    }
}

One of the business requirements is that logs are being generated for certain functions, so naturally I want to mock out the ILog to verify.

However, Common.Logging library supports type-based loggers, along the lines of:

var logger = LogManager.GetLogger<LoggedFoo>();

...or:

var logger = LogManager.GetLogger(typeof(LoggedFoo));

The problem is, we are using AutoFac for dependency injection, and I cannot figure out how to instantiate an ILog based upon the class that is being instantiated for injection.

How do I write this? I am using the latest Nuget version of AutoFac.

Jeremy Holovacs
  • 22,480
  • 33
  • 117
  • 254

2 Answers2

5

I can think on 2 ways to achieve it:(well sorry the hour is 1:50 am in my country...)

  1. Change your ILog to ILog<T> and then register it as an Open Generic.

  2. Use Dynamic-Providers which allows you to resolve with a context.

Autofac's website has an example which seems to be the exact thing you were looking for.

Resolve the dependency with a context:

private static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
    var t = e.Component.Target.Activator.LimitType;
    e.Parameters = e.Parameters.Union(
    new[]
    {
      new ResolvedParameter((p, i) => p.ParameterType == typeof(ILog), 
                            (p, i) => LogManager.GetLogger(t)),
    });
}

Attach to:

protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
    // Handle constructor parameters.
    registration.Preparing += OnComponentPreparing;

    // Handle properties.
    registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance);
}
Old Fox
  • 8,629
  • 4
  • 34
  • 52
2

So recently I decided the best way to do this was not to inject the ILog interface, but rather the ILogManager interface, like so:

public class Foo
{
    private readonly ILog _logger;
    public Foo(ILogManager logManager)
    {
        _logger = logManager.GetLogger<Foo>();
    }
}

By doing this, I cut out a lot of the headscratching necessary to figure out which logger needed to be referenced. I defined my ILogManager class once with an SingleInstance lifetime and never looked back.

Jeremy Holovacs
  • 22,480
  • 33
  • 117
  • 254