【问题标题】:ILoggerFactory in extension method - lifetime and dispose扩展方法中的 ILoggerFactory - 生命周期和处置
【发布时间】:2017-07-13 06:37:17
【问题描述】:

要在扩展方法中创建 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'。 在 Microsoft.Extensions.Logging.LoggerFactory.CreateLogger(字符串 categoryName) 在 Microsoft.Extensions.Logging.Logger`1..ctor(ILoggerFactory 工厂) 在 Microsoft.Extensions.Logging.LoggerFactoryExtensions.CreateLogger[T](ILoggerFactory 工厂)

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

【问题讨论】:

  • 为什么需要在扩展方法中做登录?
  • 你为什么要这样做?
  • 出于同样的原因在别处添加日志记录。
  • ILoggerFactory 默认注册为 Singleton。内置 DI 不应“意外”处理它。你什么时候收到ObjectDisposedException
  • 我随机获取一些请求 - 我的应用程序是一个自托管的 Web API。我不会在我的代码中的任何地方放置它。其实这篇msdn文章提出了保持静态logger factorymsdn.microsoft.com/en-us/magazine/mt694089.aspx的模式

标签: c# asp.net-core .net-core asp.net-core-1.0


【解决方案1】:

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

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

内部简单地做

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

无论如何,正如其他 cmets 所说 - 尽量使用内置的 DI 容器,而不是使用自己的静态类来解决依赖关系。

【讨论】:

  • 如何在扩展方法中使用内置的DI容器?
  • 除非您直接将服务解析器作为方法的参数传递,否则它不能。您不应该将工厂方法作为扩展方法的主要思想。将ApplicationLogging 类作为具有公共方法的简单类,然后将其作为Startup.ConfigureServices 方法中的单例注册到DI 容器,然后通过构造函数将其注入...
  • 感谢集。然后回到原来的问题。扩展方法如何访问ApplicationLogging实例?
  • @ubi,好的,你有没有试过你已经拥有的但添加了services.AddLogging();
  • 这里的问题是我无法始终如一地重现该问题。即使没有services.AddLogging(),它也可以正常工作-此错误随机出现在日志中。可能是当GC 来收集它清理的东西时,如果它不在 DI 容器中。将尝试添加它。
【解决方案2】:

类似:

public class MyClass
{
    private readonly ILogger _logger;
    public MyClass(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<MyClass>();
        "Test".ToSomething(_logger);
    }

     public static string ToSomething(this string source, ILogger logger)
     {
        logger.LogInformation(source);
        return source;    
     }
}

【讨论】:

    猜你喜欢
    • 2015-09-24
    • 2017-08-21
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多