【问题标题】:How use Microsoft.Extensions.Logging from Library code?如何从库代码中使用 Microsoft.Extensions.Logging?
【发布时间】:2020-04-07 08:26:39
【问题描述】:

我很难理解在通用库中使用 Microsoft.Extensions.Logging 的最佳方式是什么。

使用 NLog 你可以做到:

public class MyClass
{
    private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

    public void foo()
    {
        Logger.Info("foo");
    }
}

你就完成了!您让客户端配置其目标,但这不再是您的问题了。

但使用 Microsoft.Extensions.Logging,代码看起来更像:

public class MyClass
{
    private readonly Ilogger Logger;

    public MyClass(ILogger<MyClass> logger)
    {
        Logger = logger;
    }

    public void foo()
    {
        Logger.LogInformation("foo");
    }
}

所以现在我需要在 ctor 处传递一个 ILogger。
好的,没问题,我可以从 ILoggerFactory 获得一个。
现在我需要一个 ILoggerFactory。

  • 从哪里获得 ILoggerFactory?我只是为我的图书馆创建一个全球性的?
  • 客户端将如何配置工厂以添加他想要的 ILoggerProvider?
  • 如果客户端已正确完成配置,ILoggerFactory 是否会自动配置正确的提供程序?

这听起来不对,因为要在库代码中创建 LoggerFactory,您需要引用 Microsoft.Extensions.Logging,而您应该只引用 Microsoft.Extensions.Logging.Abstractions。这是代码异味的线索。

当您在 ASP.Net Core 应用程序或服务中但想要一个可在控制台应用程序或 WinForm/WPF 应用程序中使用的通用库时,构造函数中的依赖注入看起来不错?

  • 如果客户端库没有通用主机或不使用依赖注入怎么办?

所以现在客户端现在需要传递一个 ILogger?

//Client code
var myClass = new MyClass(); //with NLog

var myClass = new MyClass(loggerFactory.CreateLogger<MyClass>());

首先代码很糟糕,现在客户端必须在某处跟踪 ILoggerFactory。

我是否错过了什么或 Microsoft.Extensions.Logging 对于通用库来说看起来很糟糕?您是否有使用 Microsoft.Extensions.Logging 的此类项目的代码示例?

谢谢

【问题讨论】:

  • asp.net-core项目吗?
  • 不,我不在asp.net-core 项目中。您的共享链接恢复了我的情况:Accessing the Logging API Outside of a MVC Controller OK, so this is where the new logging API quickly becomes a nightmare. 我看到的最佳解决方案是库的静态配置:Create a centrally located static class or project to hold and wrap around the main LoggerFactory reference: I see this as the best solution here unless you aren’t using any providers that have concurrency issues.
  • 这个问题“仅仅”基于意见,即使它确实包含一些自以为是的措辞。它正在寻找如何在特定上下文中完成这项任务 - 独立于“通用 DI”技术的任意库。这尤其重要,因为即使是 LibLog(现已不复存在)也遵循“使用 Logging.Abstractions”而没有如何做到这一点的有用方法
  • 直接使用 NLog(建立库依赖关系,这是另一个问题)和 LibLog(使用“一个”可用的提供程序)都隐含地没有这个问题。如果有任何类型的“复杂”层次结构,例如 App ,这甚至需要处理

标签: c# logging


【解决方案1】:

听起来您遇到了库开发人员遇到的常见问题。

最终在依赖注入被视为默认设置的环境中(请参阅 .NET 核心等),要知道如何处理它可能会很棘手。

其实我不久前问过一个类似的问题:

Writing a library that is dependency-injection "enabled"

我什至写了一个实用程序库 (https://github.com/ckpearson/IoCBridge),它的构思很糟糕,旨在帮助从库的角度抽象出 DI 容器。

但是,在您的情况下,我可以看到为什么 NLog 与 .NET 日志记录方法相比看起来更优雅,但我在这里说这是一种虚假的安慰。

.NET 日志抽象使用的构造函数参数遵循Explicit Dependencies Principle,而 NLog 解决方案完全隐藏了依赖关系,更不用说允许您替换它了。

我同意,如果没有支持依赖注入的环境,它会变得有点麻烦,但这通常是一个好兆头,表明您可能想要添加依赖注入。

所以,是的,您的库类应该将记录器作为参数,调用者应该通过依赖容器解析您的类型,或者必须显式提供记录器实例。

tl;博士

您不(也不应该)在您的库中创建记录器工厂,而是应该由使用您的库的应用程序负责;如果他们使用的是支持主机构建器和依赖注入的 .NET 环境,平台将为他们解决这个问题。

我建议复习一下 Microsoft 文档:

【讨论】:

    猜你喜欢
    • 2021-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 2013-05-09
    • 2023-01-17
    相关资源
    最近更新 更多