扩展方法中的ILoggerFactory——生命周期和释放

4
为了在扩展方法中创建一个ILogger,我在静态类中存储了一个ILoggerFactory。
public static class ApplicationLogging
{
    public static ILoggerFactory LoggerFactory { get; set; }

    public static ILogger CreateLogger<T>() =>
        LoggerFactory?.CreateLogger<T>();

    public static ILogger CreateLogger(string name) =>
        LoggerFactory?.CreateLogger(name);

}

这是通过设置

public void Configure(ILoggerFactory loggerFactory)
{
   ...
    ApplicationLogging.LoggerFactory = loggerFactory;
}

然而,我注意到ILoggerFactory被释放了。

System.ObjectDisposedException:无法访问已释放的对象。 对象名称:“LoggerFactory”。 at Microsoft.Extensions.Logging.LoggerFactory.CreateLogger(String categoryName) at Microsoft.Extensions.Logging.Logger`1..ctor(ILoggerFactory factory) at Microsoft.Extensions.Logging.LoggerFactoryExtensions.CreateLogger[T](ILoggerFactory factory)

那么存储ILoggerFactory不正确吗?从扩展方法访问它的替代方法是什么?存储IServiceProviderGetRequiredService<ILoggerFactory>

2
为什么需要在扩展方法中进行日志记录? - Ignas
你为什么要这样做? - Mardoxx
出于同样的原因,在其他地方添加日志记录。 - ubi
2
ILoggerFactory 默认情况下注册为 Singleton。内置的 DI 不应该 "意外" 处理它。什么时候会出现 ObjectDisposedException - Ilya Chumakov
有些请求我会随机收到 - 我的应用程序是一个自托管的Web API。我在代码中没有任何处置它。实际上,这篇MSDN文章提出了保持静态日志记录器工厂模式的建议 https://msdn.microsoft.com/en-us/magazine/mt694089.aspx - ubi
我认为你需要展示更多的代码。正如Ilya所说,日志工厂是一个单例并且在各处重复使用。如果你突然遇到了disposed异常,那么肯定有其他问题(而且非单例服务至少不应该工作)。 - poke
1个回答

1

ILoggerFactory 不会被默认添加到 DI 容器中。您应该使用提供的 AddLogging() 扩展方法进行注册。

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddLogging()
}

内部简单地执行

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

无论如何,正如其他评论所说 - 尽可能使用内置的 DI 容器而不是自己的静态类进行依赖项解析。


1
内置的 DI 容器如何在扩展方法中使用? - ubi
除非您直接将服务解析器作为方法参数传递,否则无法实现。主要思想是不要将工厂方法作为扩展方法。将ApplicationLogging类作为一个简单的类,并在Startup.ConfigureServices方法中将其注册为单例,然后通过构造函数注入它... - Set
谢谢Set。然后又回到最初的问题。如何从扩展方法访问ApplicationLogging实例? - ubi
@ubi,好的,你尝试过在现有代码中添加 services.AddLogging(); 吗? - Set
问题在于我无法稳定地重现这个问题。即使没有 services.AddLogging(),它也能正常工作 - 这个错误会随机出现在日志中。可能是当 GC 来收集东西时,如果它不在 DI 容器中,它就会被清理掉。将尝试添加它。 - ubi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接