在asp.net core 1.1中,我可以将IServiceProvider注入到记录器提供程序中,并在调用CreateLogger时解析我的记录器,但在asp.net core 2.0中一切都改变了。
我的ILogger实现需要依赖注入。我该如何实现?
我的ILogger实现需要依赖注入。我该如何实现?
IServiceProvider
实例。Startup.ConfigureServices(IServiceCollection services)
方法的返回值从void更改为IServiceProvider
。您可以利用这个可能性在ConfigureServices中构建IServiceProvider实例,并用它来记录启动引导,然后从该方法返回。public interface ISomeDependency
{
}
public class SomeDependency : ISomeDependency
{
}
public class CustomLogger : ILogger
{
public CustomLogger(ISomeDependency dependency)
{
}
// ...
}
public class CustomLoggerProvider : ILoggerProvider
{
private readonly IServiceProvider serviceProvider;
public CustomLoggerProvider(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public ILogger CreateLogger(string categoryName)
{
return serviceProvider.GetRequiredService<ILogger>();
}
// ...
}
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
return ConfigureLogging(services);
}
private IServiceProvider ConfigureLogging(IServiceCollection services)
{
services.AddTransient<ISomeDependency, SomeDependency>();
services.AddSingleton<ILogger, CustomLogger>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new CustomLoggerProvider(serviceProvider));
return serviceProvider;
}
// ...
}
首先需要讲一下在不同场合中所需的依赖项
public class SomeDependency : ISomeDependency
{
}
public static class ApplicationLoggerFactoryExtensions
{
public static ILoggingBuilder CustomLogger(this ILoggingBuilder builder)
{
builder.Services.AddSingleton<ILoggerProvider, CustomLoggerProvider>();
//Be careful here. Singleton may not be OK for multi tenant applications - You can try and use Transient instead.
return builder;
}
}
ILoggerProvider
的存在可能就有意义了。public class CustomLoggerProvider : ILoggerProvider
{
private ISomeDependency someDependency;
public CustomLoggerProvider(ISomeDependency someDependency)
{
this.someDependency = someDependency;
}
public ILogger CreateLogger(string categoryName)
{
return new CustomeLogger(someDependency);
}
}
public class CustomLogger : ILogger
{
public CustomLogger(ISomeDependency dependency)
{
}
}
在你配置ServiceCollection的地方...就像OP在Startup.cs中提出的问题一样。
private void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISomeDependency, SomeDependency>();
//services.AddSingleton<ILogger, CustomLogger>(); <== NO
var loggerFactory = new LoggerFactory(); //??? newer DotNet gives you LoggerFactory in startup this may be unnecessary.
//Add some console printer
services.AddLogging(configure => configure.AddConsole())
.Configure<LoggerFilterOptions>(options => options.MinLevel = LogLevel.Trace);
//Add our custom logger
services.AddLogging(configure => configure.CustomLogger()); // <== our extension helping out!
}
✘ 不要 - 不要将任何ILogger添加到您的服务中
LoggerFactory
和LoggerProvider
配置的整个目的是简化使用ILogger
public MyBusinessService(ILogger<BusinessServiceClass> log)
{
log.Information("Please tell all registered loggers I am logging!);
}
private static void ConfigureApplicationLogging(WebHostBuilderContext context, ILoggingBuilder loggingBuilder)
{
loggingBuilder.AddConfiguration(context.Configuration.GetSection("Logging"));
loggingBuilder.AddDebug();
loggingBuilder.AddConsole();
var serviceProvider = loggingBuilder.Services.BuildServiceProvider();
loggingBuilder.AddProvider(new DoxErrorLoggerProvider(serviceProvider, null));
}
然后在BuildWebHost中,您将按以下方式配置日志记录:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(ConfigureApplicationLogging)
.UseNLog()
.UseStartup<Startup>()
.Build();