Using Asp.Net Core 2 Injection for Serilog with Multiple Projects Using Asp.Net Core 2 Injection for Serilog with Multiple Projects asp.net asp.net

Using Asp.Net Core 2 Injection for Serilog with Multiple Projects


One method that worked for me:

I added an instance of Serilog.Core.Logger using the AddSingleton() method in the ConfigureServices method. This resolved the DI issue. This step replaces the step of assigning a Logger instance to Log.Logger in the StartUp constructor.

services.AddSingleton((ILogger)new LoggerConfiguration()            .MinimumLevel.Information()            .WriteTo.File(<...>)            .CreateLogger());

Also change references in your class files to point to Serilog.Ilogger


This solution correctly injects the logger into classes in an external project or library.

I also tried the answer suggested by Rufus. I didn't have the problem described by the OP, but I had an even weirder problem: after ILogger was injected into the external project, logging to MS SQL stopped working. Console logging worked. Since Serilog is mainly a static service, I realized I should treat Log.Logger as the factory. The benefit is that you can still customize ILogger references (for example, adding ForContext in the constructor) without affecting the "singleton" service.

I've posted a full working solution on github including a console program that sets up DI (would work the same from ASP.NET Core), an external library that contains the Serilog getting-started divide-by-zero demo, and another library that manages Serilog as a service.

The important part, Serilog service registration, looks like this (and as a bonus, we tie to ProcessExit for transparent cleanup):

using Microsoft.Extensions.DependencyInjection;using System;namespace Serilog.Injection{    public static class RegisterSerilogServices    {        public static IServiceCollection AddSerilogServices(this IServiceCollection services)        {            Log.Logger = new LoggerConfiguration()                .MinimumLevel.Verbose()                .WriteTo.Console()                .WriteTo.MSSqlServer(@"xxxxxxxxxxxxx", "Logs")                .CreateLogger();            AppDomain.CurrentDomain.ProcessExit += (s, e) => Log.CloseAndFlush();            return services.AddSingleton(Log.Logger);        }    }}


I have actually been struggling with the very same setup, but I managed to get it to work. The solution is only slightly different from your code examples in these ways:

  • It depends on the Microsoft.Extensions.Logging.ILogger.
  • The Logger is injected using ILogger<Type>

Your controller code already fit these requirements, which is why that did work.

using Microsoft.Extensions.Logging;public class HomeController : Controller{    ILogger _logger;    public HomeController(ILogger<HomeController> logger)    {        _logger = logger;        _logger.LogInformation("Controller instantiated");    }}

For other classes in other projects just make sure you depend on the default ILogger interface, not Serilog's implementation. This also has the benefit that, if you want to replace Serilog later, you can do this without having to remove all references to it throughout your other projects as well.

using Microsoft.Extensions.Logging;public class MyBusinessObject{    ILogger _logger;    public MyBusinessObject(ILogger<MyBusinessObject> logger)    {        _logger = logger;    }    public void DoBusinessLog()    {        _logger.Information("Executing Business Logic");    }}

For some reason DI only manages to instantiate a Logger instance when requiring an ILogger<Type> but not for ILogger. Why that is exactly I don't know, maybe someone else can answer that one.