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

时间:2019-08-08 02:30:20

标签: .net-core serilog

我关注这篇文章。 Developing a sink

但是我需要注入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);
    }
}

程序主程序:

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

应用设置:

{
"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "MyTestProject" ],
    "WriteTo": [
        {
            "Name": "Console",
            "Args": {
                "restrictedToMinimumLevel": "Debug"
            }
        },
        {
            "Name": "MySink",
            "Args": {
                "restrictedToMinimumLevel": "Warning"
            }
        }
    ]
}

我可以使用Args注入IHttpClientFactory吗?

还是在Main方法中处理?

注意:我正在使用网络核心控制台应用程序。

更新:根据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>();
        }
    }

我可以在其他类中注入ILogger

class Test
{
    private readonly ILogger<Test> _logger;

    Test(ILogger<Test> logger)
    {
        _logger = logger;
    }
}

1 个答案:

答案 0 :(得分:1)

我玩了一段时间,发现您可以在构建服务提供者之后使用实现工厂来获取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");
}

在代码示例中,我们可以使用AddSingleton的工厂实现来仅在首次请求记录器时创建记录器。这使我们能够从服务提供商处提取所有注册的服务,并将其注入到我们的课程中。在这种情况下,我们得到IHttpClientFactory并将其注入MySink

如果您在进入行var logger = serviceProvider.GetService<Serilog.ILogger>()时在其上放置一个断点,它将在AddSingleton中调用lambda并为您创建记录器。