【问题标题】:Should private class member use its own ILogger instance? [closed]私有类成员是否应该使用自己的 ILogger 实例? [关闭]
【发布时间】:2021-08-12 08:32:14
【问题描述】:

我正在编写一个 C# 库,并试图弄清楚如何最好地进行日志记录。我希望我的库在有和没有 DI 的情况下都可以使用。

假设我的库有一个名为Foo 的主要公共类,它通过其构造函数接受IBar 依赖项,但也有一个类型为Qux 的硬连线私有成员(一个内部类)。

为了使我的库日志框架不可知,我认为最佳实践是将ILogger<Foo> 传递给Foo 的构造函数,并将ILogger<BarImpl> 传递给IBar 的实现。

我的问题是,Qux 应该使用 ILogger<Foo> 记录器,还是应该有自己的记录器 ILogger<Qux>?如果是这样,Foo 将如何创建一个ILogger<Qux> 以传递给Qux

public interface IBar {}

public class BarImpl : IBar
{
    public BarImpl(ILogger<BarImpl> logger)
    {
    }
}

internal class Qux
{
    public Qux(ILogger<Qux> logger) // should Qux accept ILogger<Qux> or ILogger<Foo>?
    {
    }
}

public class Foo
{
    private Qux _qux;
    
    public Foo(IBar bar, ILogger<Foo> logger)
    {
        // how to create ILogger<Qux> here?
        // _qux = new Qux();
    }
}

【问题讨论】:

  • 你不能把Qux也注入Foo,让容器自己解决吗?
  • 谢谢你,两位记录者是指ILogger&lt;Foo&gt;ILogger&lt;Qux&gt;吗?
  • @Llama Qux 是一个内部类,我想对Foo 的用户隐藏它。它应该被视为一个实现细节。
  • 正如@CamiloTerevinto 所说,ILoggerFactory 是您应该使用的基础设施类型代码。
  • 静态依赖解决是一件很痛苦的事情,因为你到处都有隐藏的依赖。在查看类签名时,无法知道内部的日志记录系统存在隐藏的依赖关系以及它是如何工作的。根据我的经验,隐藏的依赖关系会在你最意想不到的时候回来咬你。

标签: c# .net logging dependency-injection ilogger


【解决方案1】:

您有几种方法可以做到这一点。

  1. 如果您希望 Qux 像现在一样成为 Foo 的实现细节,那么:
public Foo(IBar bar, ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger<Foo>();
    _qux = new Qux(loggerFactory.CreateLogger<Qux>());
}
  1. 如果您想更正确地使用 DI,并且可以依赖用户正确使用您的库(如 @Llama 所建议的那样):
public Foo(IBar bar, Qux qux, ILogger<Foo> logger)
{
    _logger = logger;
    _qux = qux;
}

// inside your library where you can see the internal Qux
public static IServiceCollection InjectMyLibraryServices(this IServiceCollection services)
{
    // ...
    services.AddScoped<IQux, Qux>();
    services.AddScoped<IFoo, Foo>();
}
  1. 您可以摆脱Qux 的 DI 并获取记录器(如 @canton7 所述):
public Foo(IBar bar, ILogger<Foo> logger)
{
    _logger = logger;
    _qux = new Qux();
}

internal class Qux 
{
    private readonly ILogger _logger = LogManager.GetLogger(typeof(Qux));
}

旁注:最后一种方法代表了服务定位器反模式并隐藏了日志记录依赖项。仅当您了解以这种方式做事的利弊时才使用。我个人不会推荐这种方法。

【讨论】:

  • 非常感谢@Camilo。这很有帮助。
  • 它并不是真正的服务定位器——服务定位器可用于获取任何类型的依赖。静态日志管理器只能用于获取记录器。范围明显更小,这减轻了几乎所有的担忧
猜你喜欢
  • 2014-03-15
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多