定义
我们有 3 个接口:ILogger、ILoggerProvider 和 ILoggerFactory。让我们看看source code找出他们的职责:
ILogger:负责写入给定Log Level的日志消息。
ILoggerProvider:负责创建ILogger的实例(你不应该直接使用ILoggerProvider来创建记录器)
ILoggerFactory:您可以向工厂注册一个或多个ILoggerProviders,然后工厂使用它们来创建ILogger 的实例。 ILoggerFactory 拥有 ILoggerProviders 的集合。
在下面的示例中,我们向工厂注册了 2 个提供程序(控制台和文件)。当我们创建一个记录器时,工厂使用这两个提供者来创建一个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
因此,记录器本身正在维护ILoggers 的集合,并将日志消息写入所有这些集合。 Looking at Logger source code我们可以确认Logger有一个ILoggers的数组(即LoggerInformation[]),同时它实现了ILogger接口。
依赖注入
MS documentation 提供了 2 种注入 logger 的方法:
1.注入工厂:
public TodoController(ITodoRepository todoRepository, ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApi.Controllers.TodoController");
}
创建一个 Category = TodoApi.Controllers.TodoController 的 Logger。
2。注入泛型ILogger<T>:
public TodoController(ITodoRepository todoRepository, ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
使用 Category = TodoController 的完全限定类型名称创建一个记录器
在我看来,使文档混乱的是它没有提到任何关于注入非泛型 ILogger 的内容。在上面的同一个例子中,我们注入了一个非泛型的ITodoRepository,然而,它并没有解释为什么我们没有对ILogger做同样的事情。
根据Mark Seemann:
注入构造函数应该只接收
依赖关系。
将工厂注入Controller不是一个好方法,因为初始化Logger不是Controller的责任(违反SRP)。同时注入一个通用的ILogger<T> 会增加不必要的噪音。查看Simple Injector 的博客了解更多详情:What’s wrong with the ASP.NET Core DI abstraction?
应该注入(至少根据上面的文章)是非泛型ILogger,但是,这不是微软的内置 DI 容器可以做的事情,你需要使用 3rd 方 DI图书馆。 Thesetwo 文档解释了如何将 3rd 方库与 .NET Core 一起使用。
这是 Nikola Malovic 的 another article,他在其中解释了他的 5 条 IoC 定律。
尼古拉的国际奥委会第四定律
正在解析的类的每个构造函数都不应该有任何
除了接受一组自己的依赖项之外的实现。