【问题标题】:.Net Core 3 dependency injection of a Serilog.Net Core 3 Serilog 的依赖注入
【发布时间】:2020-03-13 16:25:40
【问题描述】:

我正在做一个使用 Serilog 的 Windows 服务

这对工人来说很好:

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;
    }

    //.....
}

我的问题是我不知道如何在 worker 中实例化我的类 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...");
    }
}

【问题讨论】:

  • 您应该使用依赖注入容器注册 DataAccess。您可以在 ConfigureServices 中添加 services.Add&lt;DataAccess&gt;()
  • 明智的设计 如何使用数据访问?您可以注册数据访问权限并将其注入到需要的位置,但您没有提供足够的信息以供更好地为您提供建议。

标签: c# .net-core dependency-injection windows-services


【解决方案1】:

我的问题是完全混淆了依赖倒置的一般原则,并理解我需要摆脱这样的代码:

var db = new DataAccess(_connectionString);

所以我终于意识到要让它正常工作需要做的是:

程序.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() 可以正常工作。

【讨论】:

    【解决方案2】:

    希望对您有所帮助。

    首先,注册依赖项的正确位置是在StartUp 类的ConfigureServices 中。然后框架负责创建依赖项的实例并在不再需要时将其处理掉。

    您可以使用以下代码 sn-p 在注入容器中注册DataAccess(正如@JamesFaix 在他的评论中所写):services.Add&lt;DataAccess&gt;()

    正如文档中 Microsoft 的文章 Service lifetimes 中所述,服务具有一定的生命周期,可以是:

    • 瞬态:瞬态生命周期服务 (AddTransient) 是在每次从服务容器请求时创建的。这个生命周期最适合轻量级、无状态的服务

    • Scoped:Scoped 生命周期服务 (AddScoped) 为每个客户端请求(连接)创建一次。

    • Singleton:Singleton 生命周期服务 (AddSingleton) 在第一次被请求时创建(或者在 Startup.ConfigureServices 运行并使用服务注册指定实例时)。

      要进一步了解注册服务和依赖注入,请查看以下文章:Dependency injection in ASP.NET Core

    除此之外,如果您想要一条更实用和更易于理解(在我看来)的路径供您遵循,我将把它留在这里:Dependency Injection in ASP.NET Core MVC

    【讨论】:

      猜你喜欢
      • 2016-05-22
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      • 2021-07-15
      • 2020-02-05
      相关资源
      最近更新 更多