I'm trying to inject my Serilog Logger into a .Net Standard 2.0 library class from a .NET Core Worker Service Project. However whenever the SetManager
class is created, it is receiving no logger. (The default is set to null) Therefore I get a value is null error whenever I try use the logger.
Can anyone help? Host Builder Below
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
ConfigDto configDto = configuration.GetSection("AppSettings").Get<ConfigDto>();
services.AddSingleton(configDto);
services.AddHostedService<Service>();
})
.UseSerilog();
}
Class in Worker Project that calls SetManager which is the Class in the .NET Standard Library.
public Service(ConfigDto config, ILogger<Service> logger = null)
{
_logger = logger;
_logger.LogTrace("Service object created");
try
{
_logger.LogTrace("Getting config");
_config = config;
}
catch (Exception ex)
{
_logger.LogCritical("Unable to load configuration. Stopping service:\n{0}", ex.Message);
Stop();
}
_setManager = new SetManager(_config);
_setManager.ReadyToProcess += SetManager_ReadyToProcess;
}
SetManager Constructor
public SetManager(ConfigDto config, ILogger<SetManager> logger = null)
{
_logger = logger;
_config = config;
_productList = GetProducts();
_timer.Interval = 3000;
_timer.Elapsed += Timer_Elapsed;
}
Packages
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" /> `
The Service
class gets the logger injected fine. Its the SetManager
class that doesn't receive the logger.
Serilog Logger setup in Main method.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.With(new ThreadIdEnricher())
.Enrich.FromLogContext()
.WriteTo.Console(LogEventLevel.Verbose, loggerTemplate, theme: AnsiConsoleTheme.Literate)
.WriteTo.File(logfile, LogEventLevel.Verbose, loggerTemplate, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 90)
.CreateLogger();
The Service class gets the logger injected fine. Its the Set Manager class that doesn't receive the logger.
You are manually creating the SetManager
_setManager = new SetManager(_config);
using the constructor with the default (null) logger.
I would suggest explicitly injecting the manager into the service worker
public Service(SetManager manager, ILogger<Service> logger)
{
_logger = logger;
_logger.LogTrace("Service object created");
try
{
_logger.LogTrace("configuring manager");
_setManager = manager;
_setManager.ReadyToProcess += SetManager_ReadyToProcess;
}
catch (Exception ex)
{
_logger.LogCritical("Unable to load configuration. Stopping service:\n{0}", ex.Message);
Stop();
}
}
Making sure that the manager is also registered with the service collection with an appropriate lifetime scope
This will allow the correct Logger to be injected into the manager when the manager is injected into the service and follows the Explicit Dependencies Principle