Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I inject dependencies into a custom ILogger in asp.net core 2.0?

In asp.net core 1.1 I could inject the IServiceProvider into the logger provider and resolve my logger when CreateLogger was called, but it all changed in asp.net core 2.0

My ILogger implementation needs dependencies injected. How can I achieve this?

like image 340
Clement Avatar asked Nov 15 '17 05:11

Clement


People also ask

How can we inject the service dependency into the controller?

ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. The built-in container is represented by IServiceProvider implementation that supports constructor injection by default.

How many types of dependency injection are there in ASP.NET Core?

NET Core provides three kinds of dependency injection, based in your lifetimes: Transient: services that will be created each time they are requested. Scoped: services that will be created once per client request (connection) Singleton: services that will be created only at the first time they are requested.


2 Answers

ASP.NET core provides possibility to replace built-in DI container with custom one (see this article for details). You could use this possibility to obtain instance of IServiceProvider earlier for logging bootstrapping while still using standard .Net core DI container.

To do this you should change return value of Startup.ConfigureServices(IServiceCollection services) method from void to IServiceProvider. You can use this possibility to build instance of IServiceProvider in ConfigureServices, use it for logging bootstrapping and then return from the method.

Sample code:

public interface ISomeDependency
{
}

public class SomeDependency : ISomeDependency
{
}

public class CustomLogger : ILogger
{
    public CustomLogger(ISomeDependency dependency)
    {
    }

    //  ...
}

public class CustomLoggerProvider : ILoggerProvider
{
    private readonly IServiceProvider serviceProvider;

    public CustomLoggerProvider(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return serviceProvider.GetRequiredService<ILogger>();
    }

    //  ...
}

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        return ConfigureLogging(services);
    }

    private IServiceProvider ConfigureLogging(IServiceCollection services)
    {
        services.AddTransient<ISomeDependency, SomeDependency>();
        services.AddSingleton<ILogger, CustomLogger>();
        IServiceProvider serviceProvider = services.BuildServiceProvider();

        var loggerFactory = new LoggerFactory();
        loggerFactory.AddProvider(new CustomLoggerProvider(serviceProvider));

        return serviceProvider;
    }

    //  ...
}
like image 155
CodeFuller Avatar answered Sep 18 '22 19:09

CodeFuller


If you are configuring logging in program.cs you can create a function to configure logging and get an instance of logging provider like this:

private static void ConfigureApplicationLogging(WebHostBuilderContext context, ILoggingBuilder loggingBuilder)
    {
        loggingBuilder.AddConfiguration(context.Configuration.GetSection("Logging"));
        loggingBuilder.AddDebug();
        loggingBuilder.AddConsole();

        var serviceProvider = loggingBuilder.Services.BuildServiceProvider();
        loggingBuilder.AddProvider(new DoxErrorLoggerProvider(serviceProvider, null));
    }

Then in BuildWebHost you will configure logging as follows:

        public static IWebHost BuildWebHost(string[] args) =>            
        WebHost.CreateDefaultBuilder(args)
            .ConfigureLogging(ConfigureApplicationLogging)
            .UseNLog()
            .UseStartup<Startup>()
            .Build();
like image 39
Andrei Ciocan Avatar answered Sep 18 '22 19:09

Andrei Ciocan