使用依赖关系注入的 ILogger 的基类类型<T>



我有一个基类可以做一些工作,包括日志记录。我有一个 ILogger 依赖项注入到构造函数中

public abstract class BaseClassExample
{
protected readonly ILogger<BaseClassExample> logger;
public BaseClassExample(ILogger<BaseClassExample> logger)
{
this.logger = logger;
}
}

我希望类实现BaseClassExample,并做自己的工作,也包括日志记录。

public class DerivedClass : BaseClassExample
{
protected readonly ILogger<DerivedClass> logger;
public DerivedClass(ILogger<DerivedClass> logger)
{
this.logger = logger;
}
}

这是正确的做事方式吗?我是否应该获取实现类的类型来记录基类?我应该有一个单独的记录器实例(具有衍生类的类型)还是尝试使用与基类相同的记录器实例?

在基类中使用无泛型 ILogger,但在派生类中使用ILogger<DerivedClass>。这样,如果需要,您可以简单地将 ILogger 传递给基类:

public abstract class BaseClassExample
{
private readonly ILogger logger;
public class BaseClassExample(ILogger logger)
{
this.logger = logger;
}
}

public class DerivedClass : BaseClassExample
{
private readonly ILogger<DerivedClass> logger;
public class BaseClassExample(ILogger<DerivedClass> logger)
:base(logger)
{
this.logger = logger;
}
}

这样,如果您以某种方式最终得到两个派生类,您不仅可以更轻松地使用它,还可以在这两个派生类中使用 ILogger。

如果您使用的是像波纹管这样的 ASP.NET Core,请使用HttpContext.RequestServices.GetService<ILogger>

public abstract class BaseController<T> : Controller
{
private ILogger<T> _loggerInstance;
protected ILogger<T> _logger => _loggerInstance ??= HttpContext.RequestServices.GetService<ILogger<T>>();
}

如果您使用的是 Razor 页面:

class BasePageModel<T> : PageModel where T : class
{
private ILogger<T> _loggerInstance;
protected ILogger<T> _logger => _loggerInstance ??= HttpContext.RequestServices.GetService<ILogger<T>>();
}

修复@F_IVI_L的答案。

正确注入和继承记录器的代码是:

public abstract class BaseClass
{
protected readonly ILogger logger;
protected BaseClass(ILogger<BaseClass> logger)
{
this.logger = logger;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(ILogger<DerivedClass> logger) :
base(logger)
{ }
}

因为ILogger<T>是协变的,所以你可以在基类的构造函数中使用ILogger<BaseClass>,并用ILogger<DerviedClass>调用它。

在任一使用ILoggerILogger<T>的方法中,注入的记录器开始写入与预期类别不同的类别。这意味着基类将记录派生记录器类别。

如果你看一下声明:

public interface ILogger<out TCategoryName> : ILogger

它为您提供了两个选项:

  1. 使用Ilogger因为ILogger<T>ILogger
  2. 使用ILogger<BaseClass>因为ILogger<DerivedClass>也是一个ILogger<BaseClass>

最新更新