Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该服用伊洛格,伊洛格<;T>;,库的iLogger工厂或iLogger提供程序?_C#_.net_Logging_.net Core_.net Standard - Fatal编程技术网

C# 我应该服用伊洛格,伊洛格<;T>;,库的iLogger工厂或iLogger提供程序?

C# 我应该服用伊洛格,伊洛格<;T>;,库的iLogger工厂或iLogger提供程序?,c#,.net,logging,.net-core,.net-standard,C#,.net,Logging,.net Core,.net Standard,这可能在某种程度上与库设计相关,而与使用这些库的实际应用程序如何实现其日志记录无关 我正在编写一个.net标准2.0库,它将通过Nuget安装,为了让使用该库的人能够获得一些调试信息,我依赖于允许注入标准化的记录器 但是,我看到了多个接口,web上的示例代码有时使用ILoggerFactory,并在类的ctor中创建一个记录器。还有ILoggerProvider,它看起来像工厂的只读版本,但是实现可能实现也可能不实现这两个接口,所以我不得不选择。(工厂似乎比供应商更常见) 我看到的一些代码使用非

这可能在某种程度上与库设计相关,而与使用这些库的实际应用程序如何实现其日志记录无关

我正在编写一个.net标准2.0库,它将通过Nuget安装,为了让使用该库的人能够获得一些调试信息,我依赖于允许注入标准化的记录器

但是,我看到了多个接口,web上的示例代码有时使用
ILoggerFactory
,并在类的ctor中创建一个记录器。还有
ILoggerProvider
,它看起来像工厂的只读版本,但是实现可能实现也可能不实现这两个接口,所以我不得不选择。(工厂似乎比供应商更常见)

我看到的一些代码使用非泛型的
ILogger
接口,甚至可能共享同一个记录器的一个实例,还有一些代码在其ctor中使用
ILogger
,并期望DI容器支持开放泛型类型或显式注册库使用的每个
ILogger
变体

现在,我确实认为
ILogger
是正确的方法,而且可能是一个不接受该参数而只传递空记录器的ctor。这样,如果不需要日志记录,则不使用日志记录。然而,一些DI容器选择最大的ctor,因此无论如何都会失败


我很好奇我在这里应该做些什么来让用户头痛最少,同时如果需要的话仍然允许适当的日志记录支持。

这些都是有效的,除了
iLogger Provider
ILogger
ILogger
是您应该用来记录日志的。要获取
ILogger
,请使用
ILogger工厂
ILogger
是获取特定类别记录器的快捷方式(作为类别的类型的快捷方式)

当您使用
ILogger
执行日志记录时,每个注册的
ILogger提供者都有机会处理该日志消息。直接调用
ILogger提供程序
对于使用代码来说是无效的。

ILogger
实际上是为DI制作的。ILogger的出现是为了帮助更容易地实现工厂模式,而不是您自己编写所有DI和工厂逻辑,这是ASP.NET Core中最明智的决策之一

您可以选择:

ILogger
如果需要在代码中使用工厂模式和DI模式可以使用
ILogger
,实现简单的日志记录,而不需要DI

鉴于此,
ILoggerProvider
只是处理每个已注册日志消息的桥梁。没有必要使用它,因为它不会影响您应该干预代码的任何内容。它侦听已注册的
iLogger提供程序
,并处理消息。仅此而已。

定义 我们有3个接口:
ILogger
ILoggerProvider
ILoggerFactory
。让我们看看他们的职责:

ILogger:负责编写给定日志级别的日志消息

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

ILogger工厂:您可以向工厂注册一个或多个
ILogger提供程序
s,然后工厂使用所有这些提供程序来创建
ILogger
的实例
iLogger工厂
保存一组
iLogger提供程序

在下面的示例中,我们向工厂注册了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
创建类别为TodoApi.Controllers.TodoController的记录器

2。注入通用的
ILogger

public TodoController(ITodoRepository todoRepository, ILoggerFactory logger)
{
    _todoRepository = todoRepository;
    _logger = logger.CreateLogger("TodoApi.Controllers.TodoController");
}
public TodoController(ITodoRepository todoRepository, ILogger<TodoController> logger)
{
    _todoRepository = todoRepository;
    _logger = logger;
}
public TodoController(ITodoRepository todoRepository,ILogger记录器)
{
_todoRepository=todoRepository;
_记录器=记录器;
}
创建类别为TodoController的完全限定类型名称的记录器


在我看来,让文档混淆的是它没有提到任何关于注入非泛型,
ILogger
。在上面的同一个例子中,我们正在注入一个非泛型的
ITodoRepository
,但它并没有解释为什么我们对
ILogger
不这样做

根据:

注入构造函数只应接收 依赖关系

将工厂注入控制器不是一个好方法,因为初始化记录器不是控制器的责任(违反SRP)。同时,注入通用的
ILogger
会增加不必要的噪音。有关更多详细信息,请参阅Simple Injector的博客:

应该注入的(至少根据上面的文章)是一个非通用的
ILogger
,但是,这不是微软内置的DI容器可以做到的,您需要使用第三方DI库。文档解释了如何将第三方库与.NET Core一起使用


这是尼古拉·马洛维奇(Nikola Malovic)的作品,他在其中解释了国际奥委会的5条法律

国际奥委会尼古拉第四定律

正在解析的类的每个构造函数都不应该有 实现而不是接受一组自己的依赖项


对于图书馆设计,好的方法是:

  • 不要强迫使用者向类中注入记录器。只需创建另一个通过NullLoggerFactory的构造函数

    class-MyClass
    {
    私人只读iLogger工厂(loggerFactory);
    public MyClass():此(N)
    
    loggerFactory.CreateLogger("MyLibrary");
    
    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning",
          "MyLibrary": "None"
        }
      }
    }
    
    services.AddTransient(s => s.GetRequiredService<ILoggerFactory>().CreateLogger(""));