How do I fix the dependency injection so that I can access .ForContext(...)
within my worker/service class?
[.Net Core 6 for a hybrid console/WindowsService App]
In my main program class and worker/service classes, I have Serilog working correctly for basic logging...
Program.cs
Log.Information($"Application Directory: {baseDir}");
Worker.cs
_logger.LogInformation("Service Starting");
ServiceA.cs
_logger.LogInformation("In Service A");
However, the issue I'm having is that I need .ForContext to be able to work everywhere as well... and it does in my main program class:
Program.cs
Log
.ForContext("EventID", 42)
.Information("Log This with EventID === 42");
... however, when I try to do the same in either of the worker/service classes ...
Worker.cs
_logger
.ForContext("EventID", 42)
.Information("Log This with EventID === 42");
... it does not work, and I get the following error:
Error CS1061
'ILogger<Worker>' does not contain a definition for 'ForContext' and no accessible extension method 'ForContext' accepting a first argument of type 'ILogger<Worker>' could be found
... so I looked into that, and came upon the following SO questions (neither of which was I able to apply, see comments in code below) which were close:
- Hot to get Serilog to work with Depedency Injection?
- Serilog DI in ASP.NET Core, which ILogger interface to inject?
- Inject Serilog's ILogger interface in ASP .NET Core Web API Controller
... (as well as some other places) but I was unable to integrate the answers into the codebase:
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureAppConfiguration((context, config) =>
{
// Configure the app here.
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.Configure<AppSettings>(hostContext.Configuration.GetSection("AppSettings"));
services.AddScoped<IServiceA, ServiceA>();
services.AddScoped<IServiceB, ServiceB>();
//?? I'm not sure if this .AddLogging(...) is needed ??
services.AddLogging(x =>
{
x.ClearProviders();
x.AddSerilog(dispose: true);
});
//?? ... having/not having it doesn't seem to affect execution
})
.UseSerilog();
Worker.cs
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
//private readonly Serilog.ILogger<Worker> _logger;
//?? ... wrt this attempt, Serilog.ILogger won't allow <Worker> ...
//?? private readonly ILogger _log = Log.ForContext<SomeService>();
//private readonly ILogger _logger = Log.ForContext<Worker>();
//?? ... wrt this attempt, Log isn't available ...
private FileSystemWatcher _folderWatcher;
private readonly string _inputFolder;
private readonly IServiceProvider _services;
public Worker(ILogger<Worker> logger, IOptions<AppSettings> settings, IServiceProvider services)
{
_logger = logger;
_services = services;
_inputFolder = settings.Value.InputFolder;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.CompletedTask;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger
.ForContext("EventID", 1001)
.LogInformation("Service Starting - need to assign EventID === 1001");
//?? here is where .ForContext is needed (but doesn't work)
... ... ...