简体   繁体   中英

.Net Core Worker Service Injecting logging into .Net Standard Library Class

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

If the Logger class object is "null" then can't access their properties so that you can't log. If logger object is null and you want to log him then you can use another source.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM