定义
我们有3个接口:ILogger
,ILoggerProvider
和ILoggerFactory
。让我们看一下源代码以找出他们的职责:
ILogger:负责编写给定日志级别的日志消息。
ILoggerProvider:负责创建的实例ILogger
(不应ILoggerProvider
直接使用它来创建记录器)
ILoggerFactory:您可以ILoggerProvider
在工厂注册一个或多个,然后依次使用它们全部创建的实例ILogger
。ILoggerFactory
持有的收藏ILoggerProviders
。
在下面的示例中,我们正在工厂注册2个提供程序(控制台和文件)。创建记录器时,工厂将使用这两个提供程序来创建记录器实例:
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 的集合,并将日志消息写入所有记录。查看Logger源代码,我们可以确认它Logger
具有ILoggers
(LoggerInformation[]
)数组,同时正在实现ILogger
接口。
依赖注入
MS文档提供了两种注入记录器的方法:
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(违反SRP)不是Controller的责任。同时注入泛型ILogger<T>
会增加不必要的噪音。有关更多详细信息,请参见Simple Injector的博客:ASP.NET Core DI抽象有什么问题?
(至少根据上面的文章)应该注入的是非泛型的ILogger
,但是,那不是Microsoft的内置DI容器可以做到的,您需要使用第三方的DI库。这 两个文档说明了如何在.NET Core中使用第三方库。
这是Nikola Malovic 撰写的另一篇文章,他在其中解释了他的IoC的5条定律。
尼古拉的IoC第四定律
被解析类的每个构造函数除了接受一组自己的依赖关系之外,都不应具有任何实现。