我想在我的MVC控制器抽象基类中构建我的log4net记录器,如下所示:
protected static readonly ILog Log = LogManager.GetLogger(typeof(AuthorizedController));
通过这种方式,我可以定义一次记录器并完成它。唯一的问题是日志输出中的logger属性始终为AuthorizedController
,如果我从FooController
继承AuthorizedController
,我希望日志输出反映出来。
这样做会有什么好的KISS,DRY和有效的方式吗?
答案 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一起使用日志记录的示例