. Net Инъекция ядра 3 в Serilog - PullRequest
2 голосов
/ 13 марта 2020

Я выполняю Windows службу, в которой я использую Serilog

, это нормально на рабочем месте:

public class Worker: BackgroundService
{
    private readonly ILogger<Worker> _logger;

    private readonly IConfiguration _configuration;
    private readonly string _connectionString;
    private bool _serviceIsStarting = true;

    public Worker(ILogger<Worker> logger, IConfiguration iConfig)
    {
        _logger = logger;
        _configuration = iConfig;
        _connectionString = _configuration.GetConnectionString("DestinationDatabase");
    }

    //....

}

Мой Program.cs содержит это:

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
            .ReadFrom.Configuration(hostingContext.Configuration))
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
        });
}

Все хорошо, но затем я хочу добавить регистратор в мой пользовательский класс, который использует экземпляр Worker:

public class DataAccess
{
    private readonly string _connectionString;

    private readonly ILogger<DataAccess> _logger;

    public DataAccess(ILogger<DataAccess> logger, string connectionString)
    {
        _connectionString = connectionString;
        _logger = logger;
    }

    //.....
}

Моя проблема в том, что я не знаю, как создать экземпляр класса DataAccess на рабочем месте. или к внедрению зависимости здесь.

Вот [упрощенная] версия моего класса:

using Microsoft.Extensions.Logging;
using Dapper;

public class DataAccess
{
    private readonly string _connectionString;
    private readonly ILogger<DataAccess> _logger;

    public DataAccess(ILogger<DataAccess> logger, string connectionString)
    {
        _logger = logger;
        _connectionString = connectionString;
    }
    public void SaveInspection(InspectionElm inspection)
    {
        using IDbConnection connection = new System.Data.SqlClient.SqlConnection(_connectionString);
        connection.Open();

        var p = new DynamicParameters();
        p.Add("@RodNumber", inspection.RodNumber);
            p.Add("@InspectionDate", Convert.ToDateTime(inspection.InspectionDate));
            p.Add("@MeasurementEnd", Convert.ToDateTime(inspection.MeasurementEnd));
            p.Add("@InspectionResultPass", Convert.ToBoolean(inspection.InspectionResultPass));;

        connection.Execute("InsertTindasjaMasterRecord", p, commandType: CommandType.StoredProcedure);

        _logger.LogInformation("Log something...");
    }

    public void InitMesureResultTypes()
    {
        using IDbConnection connection = new System.Data.SqlClient.SqlConnection(_connectionString);
        connection.Open();
        connection.Execute("InitMeasureResultType", null, commandType: CommandType.StoredProcedure);

        _logger.LogInformation("Log something...");
    }
}

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Надеюсь, вы найдете это полезно.

Прежде всего, правильное место для регистрации зависимостей находится внутри ConfigureServices класса StartUp. Затем фреймворк берет на себя ответственность за создание экземпляра зависимости и его утилизацию, когда он больше не нужен.

Вы можете зарегистрировать DataAccess в контейнере для инъекций, используя следующий фрагмент кода (как @JamesFaix написал в своем комментарии): services.Add<DataAccess>()

Также, как описано в статье Microsoft Срок службы в документации, службы имеют определенный срок службы, который может быть:

  • Переходные: временные службы (AddTransient) создаются каждый раз, когда их запрашивают из контейнера служб. Это время жизни лучше всего подходит для облегченных служб без сохранения состояния
  • Область действия: службы времени жизни с ограничением (AddScoped) создаются один раз для каждого запроса клиента (соединения).
  • Singleton: службы времени жизни Singleton (AddSingleton) создаются при первом запросе (или когда запускается Startup.ConfigureServices и указывается экземпляр с регистрацией службы).

    Для получения дополнительных сведений о регистрации служб и внедрении зависимостей ознакомьтесь со следующей статьей : Внедрение зависимостей в ASP. NET Core

Кроме того, и если вы хотите, чтобы путь был более практичным и понятным (на мой взгляд) для вас, чтобы Следуйте, я оставляю это здесь: Внедрение зависимостей в ASP. NET Core MVC

0 голосов
/ 15 марта 2020

Моей проблемой было полное замешательство в отношении общих принципов инверсии зависимостей и понимания того, что мне нужно избавиться от кода, подобного этому:

var db = new DataAccess(_connectionString);

Так что я наконец понял, что нужно сделать, чтобы это работало правильно это:

Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args)
    {
        return Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
                .ReadFrom.Configuration(hostingContext.Configuration))
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
                services.AddScoped<IDataAccess, DataAccess>();        
            });
    }

Worker.cs:

public Worker(ILogger<Worker> logger, IConfiguration iConfig, IDataAccess dataAccess)
    {
        _logger = logger;
        _configuration = iConfig;
        _dataAccess = dataAccess;
    }

DataAcess.cs:

public class DataAccess: IDataAccess
{
    private readonly string _connectionString;
    private readonly ILogger<DataAccess> _logger;

    public DataAccess(ILogger<DataAccess> logger, IConfiguration iConfig)
    {
        _connectionString = iConfig.GetConnectionString("DestinationDatabase");
        _logger = logger;
    }
}

Вещи Работайте безупречно сейчас, и единственное, что мне нужно исследовать, - это какой метод использовать в .ConfigureServices:

services.AddScoped<IDataAccess , DataAccess>();

или

services.AddTransient<IDataAccess , DataAccess>();

или

services.AddSingleton<IDataAccess , DataAccess>(); 

По крайней мере, теперь я знаю, что AddScoped () работает нормально.

...