log4net logger在基类中定义

时间:2012-08-17 15:20:58

标签: c# inheritance logging static log4net

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

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

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

这样做会有什么好的KISS,DRY和有效的方式吗?

4 个答案:

答案 0 :(得分:18)

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

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

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

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

答案 1 :(得分:3)

我使用NInject作为IoC容器做了类似的事情,但我想你可以抓住这个想法与你自己的容器一起使用。 基本上我在请求类型构造函数上注入ILog,而不是绑定到实例I bind it to a provider

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

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

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

答案 2 :(得分:2)

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

    private ILog _log;
    protected ILog Log => _log ?? (_log = LogManager.GetLogger(GetType()));

答案 3 :(得分:-1)

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

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

我们在产品中使用Castle Windsor

您还可以查看this post以查找与DI一起使用日志记录的示例