释义
我们有3个接口:ILogger
、ILoggerProvider
和ILoggerFactory
.让我们来看看这source code人,看看他们的责任:
ILogger:负责编写给定Log Level的日志(log)消息.
ILoggerProvider:负责创建ILogger
的实例(您不应该直接使用ILoggerProvider
来创建记录器)
ILoggerFactory:您可以向工厂注册一个或多个ILoggerProvider
,工厂反过来使用所有ILoggerProvider
来创建ILogger
的实例.ILoggerFactory
Collection 了ILoggerProviders
本书.
在下面的示例中,我们向工厂注册了两个Provider (控制台和文件).当我们创建一个记录器时,工厂使用这两个提供程序来创建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
s的集合,并将日志(log)消息写入所有ILogger
s.Looking at Logger source code我们可以确认Logger
有一个ILoggers
(即LoggerInformation[]
)的数组,同时它正在实现ILogger
接口.
依赖项注入
MS documentation提供了两种注入记录器的方法:
1. Injecting the factory:个
public TodoController(ITodoRepository todoRepository, ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApi.Controllers.TodoController");
}
creates a Logger with Category = TodoApi.Controllers.TodoController
2. Injecting a generic 100:
public TodoController(ITodoRepository todoRepository, ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
creates a logger with Category = fully qualified type name of TodoController
在我看来,让文档混乱的是,它没有提到任何关于注入非通用的ILogger
.在上面的同一个例子中,我们正在注入一个非通用的ITodoRepository
,但它并不能解释为什么我们没有对ILogger
进行同样的操作.
根据Mark Seemann:
注入构造函数只需接收
将工厂注入控制器不是一个好方法,因为初始化记录器不是控制器的责任(违反SRP).同时,注入通用ILogger<T>
会增加不必要的噪音.详见Simple Injector's博客:What’s wrong with the ASP.NET Core DI abstraction?
应该注入的(至少根据上面的文章)是非通用的ILogger
,但这不是微软内置的DI容器所能做到的,你需要使用第三方DI库.These two个文档解释了如何使用第三方库.净核心.
这是尼古拉·马洛维奇的another article页,他在其中解释了国际奥委会的5条规则.
Nikola’s 4th law of IoC
正在解析的类的每个构造函数都不应该有