gpt4 book ai didi

c# - 每次注入(inject) ILogger 都会创建一个新的记录器吗?

转载 作者:太空狗 更新时间:2023-10-30 00:37:37 24 4
gpt4 key购买 nike

关于 the documentation 中的日志样本,有一个如何将记录器注入(inject) Controller 的示例:

public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,
ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
}

每当我将一个记录器注入(inject)到这里时,DI 框架是否会创建一个新的记录器?有没有更好的办法?

最佳答案

查看源代码很容易回答这个问题。当你做 services.AddLogging() , 默认行为是 ILogger<T> is registered as a singleton :

public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
{
// …

services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));

// …
}

所以不,ILogger<T>某种类型的实例 T只要应用程序正在运行,它们就会一直存在。所以在注入(inject) ILogger<TodoController> 时进入您的 Controller ,每次都会将相同的记录器实例传递给它。

当然这只适用于记录器,而不适用于您的 Controller 本身。默认情况下, Controller 在 DI 之外被激活,但有效地存在一个范围内的生命周期。所以在每次请求时,都会有一个新的 Controller 实例;但是那个人会得到之前的记录器实例。

回答你的最后一个问题,有没有更好的方法?不。除了这个行为已经是一个好的事实(因为不需要新的记录器实例)之外,使用日志记录的正确方法确实是注入(inject) ILogger<T>分为类型 T ,所以你得到一个正确分类的记录器实例。当后台发生许多您可能永远看不到的更昂贵的事情时,真的没有必要担心这里非常薄的记录器 ;)


ILogger<T>是一个单例,它的实例将在整个应用程序中重用。请注意,这不会对记录范围产生影响。 ILogger<T>您在应用程序中使用的实现实际上只是一个瘦包装器,它将日志记录调用转发给内部记录器(它们也是有效的单例)。所以 ILogger<T> 的生命周期实际上是不相关的,因为它们根本不保留任何状态。

日志记录范围本身使用 AsyncLocal 持久化这是一种在整个异步调用流程中保持状态的机制。这意味着日志记录范围将“神奇地”工作,而不会仅仅因为某些实例恰好在多个线程(或异步流)之间共享而泄漏到调用流之外。

关于c# - 每次注入(inject) ILogger<T> 都会创建一个新的记录器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47901666/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com