15

我想在我的 MVC 控制器抽象基类中构建我的 log4net 记录器,如下所示:

protected static readonly ILog Log = LogManager.GetLogger(typeof(AuthorizedController));

通过这种方式,我可以定义一次记录器并完成它。唯一的问题是日志输出中的 logger 属性将始终为AuthorizedController,如果我FooController继承自,AuthorizedController我希望日志输出能够反映这一点。

什么是一个好的 KISS、DRY 和有效的方法来做到这一点?

4

4 回答 4

20

我不确定调用的成本有多高LogManager.GetLogger(),但我怀疑 log4net 系统中有一些巧妙的缓存和/或延迟初始化,可以保持请求的实例可用于快速检索。毕竟,没有理由LogManager.GetLogger()使用相同的类型参数调用两次会返回不同的实例。

也就是说,也许用以下属性替换该字段就足够了。

protected ILog Logger
{
    get { return LogManager.GetLogger(GetType()); }
}

GetType()是虚拟的且重载的,因此每个具体类型将在调用此属性时提供其类型。

于 2012-08-17T15:32:04.910 回答
4

正如Steve Guidi建议的那样 - 使用 GetType 为特定类型的实例创建记录器。您可以保存对在支持字段中调用 LogManager.GetLogger 的记录器实例的引用:

    private ILog _log;
    protected ILog Log => _log ?? (_log = LogManager.GetLogger(GetType()));
于 2016-10-26T19:15:27.913 回答
3

我通过使用NInject作为 IoC 容器做了类似的事情,但我想你可以抓住这个想法来使用你自己的容器。基本上我在请求类型构造函数上注入 ILog ,但我没有绑定到实例,而是将其绑定到 provider

  kernel.Bind<ILog>().ToProvider<MyProvider>();

public object Create(IContext context)
{
    return LogManager.GetLogger(context.Request.Target.Member.DeclaringType);
}

所以每种类型都会收到一个与构造函数中相同的记录器GetLogger(GetType())

于 2012-08-17T15:34:40.350 回答
0

拥有静态记录器(或一般的静态实例)是一种不好的做法。它很容易导致不相关的组件之间出现不希望的耦合。

您应该考虑向游戏添加依赖注入/控制反转框架。将记录器注入到类的 ctor 中。大多数框架允许您在不同的上下文中定义不同的实现。

我们在产品中使用Castle Windsor

您还可以查看这篇文章以找到将日志记录与 DI 一起使用的示例

于 2012-08-17T15:35:45.547 回答