如何在 Serilog Sink 中使用依赖注入?

Lib*_*ron 8 c# serilog .net-core

我关注这篇文章。开发水槽

但我需要注入IHttpClientFactory。

public class MySink : ILogEventSink
{
    //...

    public MySink(IFormatProvider formatProvider, IHttpClientFactory httpClientFactory)
    {
        //...
    }
}

public static class MySinkExtensions
{
    public static LoggerConfiguration MySink(
        this LoggerSinkConfiguration loggerConfiguration, 
        IHttpClientFactory httpClientFactory, 
        IFormatProvider formatProvider = null,
        LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose)
    {
        return loggerConfiguration.Sink(new MySink(formatProvider, httpClientFactory), restrictedToMinimumLevel);
    }
}
Run Code Online (Sandbox Code Playgroud)

节目主要:

class Program
{
    static async Task Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddHttpClient();

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .WriteTo.MySink(null) //<--How to get IHttpClientFactory?
            .CreateLogger();

        services.AddLogging(configure => configure.ClearProviders().AddSerilog(logger));

        var serviceProvider = services.BuildServiceProvider();
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序设置:

{
"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "MyTestProject" ],
    "WriteTo": [
        {
            "Name": "Console",
            "Args": {
                "restrictedToMinimumLevel": "Debug"
            }
        },
        {
            "Name": "MySink",
            "Args": {
                "restrictedToMinimumLevel": "Warning"
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我可以使用Args来注入IHttpClientFactory吗?

或者在Main方法中处理这个问题?

注意:我正在使用 net core 控制台应用程序。

更新:根据asnwer

现在,程序主要是:

class Program
    {
        static async Task Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddHttpClient();

            serviceCollection.AddSingleton<Serilog.ILogger>(sp =>
            {
                var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();

                return new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .WriteTo.MySink(httpClientFactory)
                    .CreateLogger();
            });

            serviceCollection.AddLogging(configure => configure.ClearProviders().AddSerilog());

            var serviceProvider = serviceCollection.BuildServiceProvider();

            Log.Logger = serviceProvider.GetRequiredService<Serilog.ILogger>();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我可以在其他类中注入 ILogger

class Test
{
    private readonly ILogger<Test> _logger;

    Test(ILogger<Test> logger)
    {
        _logger = logger;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新: (2020-07-01)

现在,在 asp net core 中,该提供依赖注入。

.UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.WriteTo.SomeSink(services.GetRequiredService<ISomeDependency>()));
Run Code Online (Sandbox Code Playgroud)

Sim*_*Ged 6

我玩了一下,发现您可以使用实现工厂来在IHttpClientFactory服务提供者构建后获取。您需要更改 service.AddLogging(...) 调用以使用此工厂实现:

static async Task Main(string[] args)
{
    var serviceCollection = new ServiceCollection();
    serviceCollection.AddHttpClient();

    serviceCollection.AddSingleton<Serilog.ILogger>(sp =>
    {
        var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();

        return new LoggerConfiguration()
            .MinimumLevel.Debug()
            //.ReadFrom.Configuration(Configuration)
            .WriteTo.MySink(httpClientFactory)
            .CreateLogger();
    });

    serviceCollection.AddLogging(cfg =>
    {
        cfg.ClearProviders().AddSerilog();
    });


    var serviceProvider = serviceCollection.BuildServiceProvider();


    var logger = serviceProvider.GetService<Serilog.ILogger>();

    logger.Debug("Working");
}
Run Code Online (Sandbox Code Playgroud)

在代码示例中,我们可以使用工厂实现来AddSingleton仅在第一次请求时创建记录器。这允许我们从服务提供者处提取任何已注册的服务并将它们注入到我们的类中。在本例中,我们获取IHttpClientFactory并将其注入到 中MySink

如果您在单步执行时在该行上放置一个断点,var logger = serviceProvider.GetService<Serilog.ILogger>()它将调用 lambdaAddSingleton并为您创建记录器。