为什么.net使用通用日志记录器?



使用Microsoft的默认设置,使用ILogger<Worker>注入记录器,如下所示(直接从文档中)

public sealed class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger) =>
_logger = logger;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow);
await Task.Delay(1_000, stoppingToken);
}
}
}

与直接使用ILogger相比,这种模式提供了什么好处(我认为除了记录器的名称之外)?-或者我们失去了什么,使用ILogger没有通用部分ILogger<Worker>

我相信还有一些细微的分歧和分歧没有在这里解决https://github.com/dotnet/runtime/issues/48473但还有更多吗?

ILogger是Microsoft和其他第三方日志库(如Serilog)使用的历史接口,用于抽象日志记录器,防止开发人员将其应用程序代码耦合到单个库。这允许应用程序开发人员在需要时更改他们的日志库。

ILogger<T>继承自ILogger,是Microsoft对日志记录器的新抽象。泛型可以防止DI引擎中的冲突。还要注意的是,从。net 6开始,微软的日志库不再注册ILogger。这意味着你需要ILogger<T>注入到你的服务中。

其他库可能还没有进行更新,您可能仍然需要注入ILogger对象才能使它们工作。请参阅库文档。如果您需要兼容性,您可以手动注册ILogger,并在注入中继续使用ILogger

还要注意,你可以在注入后删除泛型部分:

public sealed class Worker : BackgroundService
{
private readonly ILogger _logger;
public Worker(ILogger<Worker> logger) => _logger = logger; // implicit cast
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow);
await Task.Delay(1_000, stoppingToken);
}
}
}

虽然不能使用标准的MS DI方法直接通过actor注入ILogger,但是有一种方法可以做到。

只需将EgonsoftHU.Extensions.Logging.Autofac nuget包添加到您的启动项目中,并按如下方式修改您的Program.cs文件:

using Autofac;
using Autofac.Extensions.DependencyInjection;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder
.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(
containerBuilder =>
containerBuilder.RegisterModule<EgonsoftHU.Extensions.Logging.Autofac.DependencyModule>();
);

你可以使用MS DI方法保留现有的依赖项注册,它们将由AutofacServiceProvider而不是Microsoft.Extensions.DependencyInjection.ServiceProvider解决。两者都实现相同的IServiceProvider接口。

现在可以注入ILogger而不是ILogger<T>

using Microsoft.Extensions.Logging;
public class Service
{
private readonly ILogger logger;
public Service(ILogger logger)
{
this.logger = logger;
}
}

当然,您可能会问,是否值得为此添加一个nuget包。

MS DI方法可能涵盖基本用例,但Autofac有高级用例的解决方案。

。在示例代码中注册的模块将自定义中间件添加到Autofac的解析管道中。这个中间件只是通过一个额外的参数扩展了参数列表,这样当需要解析一个ILogger参数时,它就会用参数的声明类型解析通用的ILogger<>类型。看到这里。

请注意:

您仍然无法直接使用IServiceProvider的扩展方法来解析ILogger实例,例如GetService<T>()GetRequiredService<T>()。相反,您可以使用ILoggerFactory.CreateLogger(string)方法。

或者您可以将ILoggerFactory注入到该函数中,并在其中创建日志记录器。

using Microsoft.Extensions.Logging;
public class Service
{
private readonly ILogger logger;
public Service(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger(GetType());
}
}

您的问题的答案可以在文档本身中找到:日志类别标题下的最后一行。从那里复制:

ILogger<T>相当于用T的完全限定类型名调用CreateLogger

相关内容

  • 没有找到相关文章

最新更新