更新时间:2022-12-13 12:26:46
现在我不确定是否已经存在一个扩展来做到这一点,但我看到了这里的潜力.
首先是 AddProvider
在源代码仓库中定义.
public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider) {builder.Services.AddSingleton(provider);返回生成器;}
您可以在此基础上制作自己的通用版本
public static class MyLoggingBuilderExtensions {公共静态 ILoggingBuilder AddProvider(这个 ILoggingBuilder 构建器)其中 T:类,ILoggerProvider{builder.Services.AddSingleton();返回生成器;}}
这应该允许 DI 容器在解析时建立对象图
services.AddLogging(builder =>{builder.AddProvider();});
并且有扩展此功能的空间,例如添加您自己的重载以公开 IServiceProvider
并将其传递给扩展中的 AddSingleton
.
public static ILoggingBuilder AddProvider(这个 ILoggingBuilder builder,Func factory)其中 T:类,ILoggerProvider {builder.Services.AddSingleton(工厂);返回生成器;}
并使用
services.AddLogging(builder => {builder.AddProvider(p => new CustomLoggerProvider(Constant value", p.GetService()));});
I am creating a custom .NET Core ILoggerProvider
that requires some dependencies to be passed into its constructor.
I believe I am using a fairly common pattern to initialize my logging implementation; it looks something like this:
var services = new ServiceCollection();
// Register some services here
services.AddLogging(builder =>
{
builder.AddProvider(new DebugLoggerProvider());
});
var provider = services.BuildServiceProvider();
I want to add my new provider within the AddLogging
block, in the same way that the DebugLoggerProvider
is currently added.
My custom provider requires some other services to be passed into its constructor and since these are already registered with the ServiceCollection
, I assume that I should be able to reference them. However, unlike methods such as AddSingleton
, which have an overload that exposes the IServiceProvider
, AddLogging
doesn't seem to offer an equivalent.
Is there a simple way to achieve this, or am I attempting to do something that contradicts the way .NET Core logging was designed to be deployed?
UPDATE:
After experimenting with the suggestions proposed by @Nkosi, I can confirm that it is possible to get this to work by bypassing AddLogging
and directly implementing what it does internally, as follows:
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();
Now I am not sure if an extension already exists to do this but I see potential here.
First this is how AddProvider
is defined in the source code repo.
public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider) {
builder.Services.AddSingleton(provider);
return builder;
}
You could build up on that by making your own generic version
public static class MyLoggingBuilderExtensions {
public static ILoggingBuilder AddProvider<T>(this ILoggingBuilder builder)
where T: class, ILoggerProvider{
builder.Services.AddSingleton<ILoggerProvider, T>();
return builder;
}
}
which should allow the DI container to build up the object graph when resolved
services.AddLogging(builder =>
{
builder.AddProvider<CustomLoggerProvider>();
});
And there is room to extend this functionality, like adding your own overload that exposes the IServiceProvider
and passing that on to the AddSingleton
within the extension.
public static ILoggingBuilder AddProvider<T>(this ILoggingBuilder builder, Func<IServiceProvider, T> factory)
where T: class, ILoggerProvider {
builder.Services.AddSingleton<ILoggerProvider, T>(factory);
return builder;
}
And used
services.AddLogging(builder => {
builder.AddProvider<CustomLoggerProvider>(p => new CustomLoggerProvider("Constant value", p.GetService<IMyService>()));
});