我应该将ILogger,ILogger< T>,ILoggerFactory或ILoggerProvider用作图书馆吗? [英] Should I take ILogger, ILogger<T>, ILoggerFactory or ILoggerProvider for a library?

查看:494
本文介绍了我应该将ILogger,ILogger< T>,ILoggerFactory或ILoggerProvider用作图书馆吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能与将ILogger或ILoggerFactory传递给AspNet Core中的构造函数有关吗?,但这与库设计,而不是关于使用这些库的实际应用程序如何实现其日志记录.

This may be somewhat related to Pass ILogger or ILoggerFactory to constructors in AspNet Core?, however this is specifically about Library Design, not about how the actual application that uses those libraries implement its logging.

我正在编写一个将通过Nuget安装的.net Standard 2.0库,并且为了允许使用该库的人们获取一些调试信息,我依赖于

I am writing a .net Standard 2.0 Library that will be installed via Nuget, and to allow people using that Library to get some debug info, I'm depending on Microsoft.Extensions.Logging.Abstractions to allow a standardized Logger to be injected.

但是,我看到了多个接口,并且网络上的示例代码有时会使用ILoggerFactory并在类的ctor中创建一个记录器.还有ILoggerProvider,它看起来像是Factory的只读版本,但是实现可能会也可能不会实现这两个接口,因此我必须选择. (工厂似乎比提供程序更常见).

However, I'm seeing multiple interfaces, and sample code on the web sometimes uses ILoggerFactory and creates a logger in the ctor of the class. There's also ILoggerProvider which looks like a read-only version of the Factory, but implementations may or may not implement both interfaces, so I'd have to pick. (Factory seems more common than Provider).

我见过的某些代码使用非通用的ILogger接口,甚至可能共享同一记录器的一个实例,有些代码在其ctor中使用ILogger<T>,并期望DI容器支持开放的通用类型或我的库使用的每个ILogger<T>变体的明确注册.

Some code I've seen uses the non-generic ILogger interface and might even share one instance of the same logger, and some take an ILogger<T> in their ctor and expect the DI container to support open generic types or explicit registration of each and every ILogger<T> variation my library uses.

现在,我确实认为ILogger<T>是正确的方法,也许是不采用该参数而仅通过Null Logger的ctor.这样,如果不需要日志记录,则不使用任何日志记录.但是,某些DI容器会选择最大的ctor,因此无论如何都会失败.

Right now, I do think that ILogger<T> is the right approach, and maybe a ctor that doesn't take that argument and just passes a Null Logger instead. That way, if no logging is needed, none is used. However, some DI containers pick the largest ctor and thus would fail anyway.

我很好奇在这里应该做的事情,以便为用户带来最少的麻烦,同时在需要时仍允许适当的日志记录支持.

I'm curious of what I'm supposed to be doing here to create the least amount of headache for users, while still allowing proper logging support if desired.

推荐答案

定义

我们有3个接口:ILoggerILoggerProviderILoggerFactory.让我们看一下源代码来找出答案他们的职责:

Definition

We have 3 interfaces: ILogger, ILoggerProvider and ILoggerFactory. Let's look at the source code to find out their responsibilities:

ILogger :负责编写给定 Log Level 的日志消息.

ILogger: is responsible to write a log message of a given Log Level.

ILoggerProvider :负责创建ILogger的实例(您不应直接使用ILoggerProvider创建记录器)

ILoggerProvider: is responsible to create an instance of ILogger (you are not supposed to use ILoggerProvider directly to create a logger)

ILoggerFactory :您可以在工厂中注册一个或多个ILoggerProvider,然后依次使用它们全部创建ILogger的实例. ILoggerFactory保存ILoggerProviders的集合.

ILoggerFactory: you can register one or more ILoggerProviders with the factory, which in turn uses all of them to create an instance of ILogger. ILoggerFactory holds a collection of ILoggerProviders.

在下面的示例中,我们正在工厂中注册2个提供程序(控制台和文件).创建记录器时,工厂将使用这两个提供程序来创建记录器实例:

In the example below, we are registering 2 providers (console and file) with the factory. When we create a logger, the factory uses both of these providers to create an instance of logger:

ILoggerFactory factory = new LoggerFactory().AddConsole();    // add console provider
factory.AddProvider(new LoggerFileProvider("c:\\log.txt"));   // add file provider
Logger logger = factory.CreateLogger(); // <-- creates a console logger and a file logger

因此,记录器本身维护着ILogger的集合,并将日志消息写入所有记录. 查看Logger源代码,我们可以确认Logger具有一个ILoggers数组(即LoggerInformation[]),并且同时正在实现ILogger接口.

So the logger itself, is maintaining a collection of ILoggers, and it writes the log message to all of them. Looking at Logger source code we can confirm that Logger has an array of ILoggers (i.e. LoggerInformation[]), and at the same time it is implementing ILogger interface.

MS文档提供了注入记录器的2种方法:

MS documentation provides 2 methods for injecting a logger:

1.注入工厂:

public TodoController(ITodoRepository todoRepository, ILoggerFactory logger)
{
    _todoRepository = todoRepository;
    _logger = logger.CreateLogger("TodoApi.Controllers.TodoController");
}

使用Category = TodoApi.Controllers.TodoController 创建一个Logger.

creates a Logger with Category = TodoApi.Controllers.TodoController.

2.注入通用ILogger<T>:

2. Injecting a generic ILogger<T>:

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

创建一个类别为TodoController的标准类型名称的记录器

在我看来,使文档令人困惑的是,它没有提及有关注入非泛型ILogger的任何内容.在上面的同一示例中,我们注入了一个非泛型的ITodoRepository,但是,它没有解释为什么我们对ILogger却没有这样做.

In my opinion, what makes the documentation confusing is that it does not mention anything about injecting a non-generic, ILogger. In the same example above, we are injecting a non-generic ITodoRepository and yet, it does not explain why we are not doing the same for ILogger.

根据马克·塞曼:

Injection构造函数只应该接受 依赖性.

An Injection Constructor should do no more than receiving the dependencies.

将工厂注入Controller并不是一个好方法,因为初始化Logger(违反SRP)不是Controller的责任.同时,注入通用ILogger<T>会添加不必要的噪声.有关更多详细信息,请参见 Simple Injector's 博客:

Injecting a factory into the Controller is not a good approach, because it is not Controller's responsibility to initialize the Logger (violation of SRP). At the same time injecting a generic ILogger<T> adds unnecessary noise. See Simple Injector's blog for more details: What’s wrong with the ASP.NET Core DI abstraction?

(至少根据上面的文章)应该注入的是非泛型ILogger,但是,那不是Microsoft的内置DI容器可以执行的操作,您需要使用第三方DI图书馆.

What should be injected (at least according to the article above) is a non-generic ILogger, but then, that's not something that Microsoft's Built-in DI Container can do, and you need to use a 3rd party DI Library.

这是

This is another article by Nikola Malovic, in which he explains his 5 laws of IoC.

尼古拉的IoC第四定律

要解析的类的每个构造函数都不应具有任何 实现,而不是接受一组自己的依赖项.

Every constructor of a class being resolved should not have any implementation other than accepting a set of its own dependencies.

这篇关于我应该将ILogger,ILogger&lt; T&gt;,ILoggerFactory或ILoggerProvider用作图书馆吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆