繁体   English   中英

Serilog 的 .Net Core 3 依赖注入

[英].Net Core 3 dependency injection of a Serilog

我正在做一个使用 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;
    }

    //.....
}

我的问题是我不知道如何在工作人员或这里的依赖注入中实例化我的类 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...");
    }
}

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

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

工人.cs:

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

数据访问.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() 工作正常。

希望你觉得这有帮助。

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

您可以使用以下代码片段(如@JamesFaix 在他的评论中所写)在注入容器中注册DataAccessservices.Add<DataAccess>()

同样如 Microsoft 文档中的服务生命周期一文所述,服务具有特定的生命周期,可以是:

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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