How to configure ConsoleLogger in console app?

4

I'm trying to build a console app, using .NET CORE 3.1, and I'm having a problem injecting a console logger.

It looks like the way that logging is injected has changed significantly, in recent versions, and none of the various flavors of instructional tutorials seem to match what I'm trying to do.

I have an interface:

public interface IMyDoer
{
    void DoSomething();
}

And a class into which I want to inject an ILogger:

public class MyDoer : IMyDoer
{
    private readonly ILogger logger;
    public MyDoer(ILogger logger)
    {
        this.logger = logger;
    }

    public void DoSomething()
    {
        this.logger.Log(LogLevel.Information, "Doing something");
    } 
}

Then I have my Main(), where I'm trying to configure a DI container to construct a Doer object, configuring ILogger to log to the console.

public class Program
{
    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);

        var serviceProvider serviceCollection.BuildServiceProvider();

        var myDoer = serviceProvider.GetService<IMyDoer>();

        myDoer.DoSomething();
    }

    private static void ConfigureServices(ServiceCollection serviceCollection)
    {
        serviceCollection.AddLogging(configure => {
            configure.AddConsole();
        });

        serviceCollection.AddSingleton<IMyDoer, MyDoer>();
    }
}

As an alternative, I've tried:

public class Program
{
    static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);

        using (var serviceProvider = serviceCollection.BuildServiceProvider())
        using (var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()))
        {
            var myDoer = serviceProvider.GetService<IMyDoer>();

            myDoer.DoSomething();
        }
    }

    private static void ConfigureServices(ServiceCollection serviceCollection)
    {
        serviceCollection
            .AddSingleton<IMyDoer, MyDoer>();
    }
}

In either case, I get an exception:

System.InvalidOperationException
  HResult=0x80131509
  Message=Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'MyDoer.DoSomething'.
  Source=Microsoft.Extensions.DependencyInjection

Any ideas as to how I should be doing this?

c#
asp.net-core
.net-core
asked on Stack Overflow Dec 26, 2019 by Jeff Dege • edited Dec 26, 2019 by Kirk Larkin

1 Answer

1

ILogger isn't registered with the ASP.NET Core DI container. Instead, use ILogger<T>:

public class MyDoer : IMyDoer
{
    private readonly ILogger<MyDoer> logger;

    public MyDoer(ILogger<MyDoer> logger)
    {
        this.logger = logger;
    }

    // ...
}

ILogger<T> uses the type name (YourNamespace.MyDoer) as the log category:

That category is included with each log message created by that instance of ILogger.

To set your own log category and create an implementation of ILogger yourself, use ILoggerFactory:

public class MyDoer : IMyDoer
{
    private readonly ILogger logger;

    public MyDoer(ILoggerFactory loggerFactory)
    {
        this.logger = loggerFactory.CreateLogger("YourCategory");
    }

    // ...
}
answered on Stack Overflow Dec 26, 2019 by Kirk Larkin • edited Dec 27, 2019 by Kirk Larkin

User contributions licensed under CC BY-SA 3.0