簡體   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