我有一个基类可以做一些工作,包括日志记录。我有一个 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>
调用它。
在任一使用ILogger
或ILogger<T>
的方法中,注入的记录器开始写入与预期类别不同的类别。这意味着基类将记录派生记录器类别。
如果你看一下声明:
public interface ILogger<out TCategoryName> : ILogger
它为您提供了两个选项:
- 使用
Ilogger
因为ILogger<T>
是ILogger
, - 使用
ILogger<BaseClass>
因为ILogger<DerivedClass>
也是一个ILogger<BaseClass>
。