如何将依赖项传递给自定义.NET Core ILoggerProvider

Tim*_*ter 3 c# logging dependency-injection .net-core .net-core-2.0

我正在创建一个自定义.NET Core ILoggerProvider,需要将一些依赖项传递给它的构造函数.

我相信我使用一种相当常见的模式来初始化我的日志记录实现; 它看起来像这样:

var services = new ServiceCollection();

// Register some services here

services.AddLogging(builder =>
{
    builder.AddProvider(new DebugLoggerProvider());
});

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

我想在AddLogging块中添加我的新提供者,就像DebugLoggerProvider当前添加的一样.

我的自定义提供程序需要将其他一些服务传递给它的构造函数,因为这些服务已经注册了ServiceCollection,我假设我应该能够引用它们.然而,与诸如AddSingleton具有暴露的过载的方法不同IServiceProvider,AddLogging似乎不提供等价物.

有没有一种简单的方法来实现这一点,或者我是否尝试做一些与.NET Core日志设计部署方式相矛盾的事情?

更新:

在试验了@Nkosi提出的建议之后,我可以确认通过绕过AddLogging并直接实现内部的工作来实现这一点,如下所示:

var services = new ServiceCollection();

// Register some services
services.AddSingleton<IMyService, MyService>();

// Initialize logging
services.AddOptions();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddSingleton<ILoggerProvider>(p => new DebugLoggerProvider());
services.AddSingleton<ILoggerProvider>(p => new MyLoggerProvider("Constant value", p.GetService<IMyService>()));

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

Nko*_*osi 7

现在我不确定是否已经存在扩展但是我在这里看到了潜力.

首先,这是如何AddProvider在源代码repo中定义的.

public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider) {
    builder.Services.AddSingleton(provider);
    return builder;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过制作自己的通用版本来构建它

public static class MyLoggingBuilderExtensions {
    public static ILoggingBuilder AddProvider<T>(this ILoggingBuilder builder)
        where T: class, ILoggerProvider{
        builder.Services.AddSingleton<ILoggerProvider, T>();
        return builder;
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该允许DI容器在解析时建立对象图

services.AddLogging(builder =>
{
    builder.AddProvider<CustomLoggerProvider>();
});
Run Code Online (Sandbox Code Playgroud)

并且还有扩展此功能的空间,例如添加自己的重载,将其暴露IServiceProvider并传递到AddSingleton扩展内.

public static ILoggingBuilder AddProvider<T>(this ILoggingBuilder builder, Func<IServiceProvider, T> factory)
    where T: class, ILoggerProvider {
    builder.Services.AddSingleton<ILoggerProvider, T>(factory);
    return builder;
}
Run Code Online (Sandbox Code Playgroud)

并使用

services.AddLogging(builder => {
    builder.AddProvider<CustomLoggerProvider>(p => new CustomLoggerProvider("Constant value", p.GetService<IMyService>()));
});
Run Code Online (Sandbox Code Playgroud)