C# 我应该在每个类还是在基类中声明一次 log4net 记录器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9071784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I declare log4net logger once per class or in base class?
提问by dev.e.loper
It seems cleaner to declare a logger and call LogManager.GetLoggerin a base class so that everyone who is inheriting can use it. However, on log4net site and other blogs like in this blog postit states that it is better to declare one logger per class because:
声明一个记录器并调用LogManager.GetLogger一个基类似乎更干净,这样每个继承者都可以使用它。但是,在 log4net 站点和本博客文章中的其他博客上,它指出最好为每个类声明一个记录器,因为:
You can use loggers this way to isolate logging concerns across your objects, and I wholly recommend you do so. This will enable you to throttle and direct log output from individual loggers using log4net's hierarchical configuration mechanism.
您可以通过这种方式使用记录器来隔离对象之间的日志记录问题,我完全建议您这样做。这将使您能够使用 log4net 的分层配置机制限制和直接从单个记录器输出日志。
Does this mean if I put it in base class, it will make that logger a bottleneck?
这是否意味着如果我把它放在基类中,它会使那个记录器成为一个瓶颈?
If so, are there other solutions or do I just have to create a logger per class?
如果是这样,是否有其他解决方案,或者我是否只需要为每个类创建一个记录器?
回答by DotNetUser
Usually you should have a single logger class, you could use singleton pattern and make sure that you have only one instance of logger for your application.
通常你应该有一个记录器类,你可以使用单例模式并确保你的应用程序只有一个记录器实例。
Edit: Made it thread safe now, thanks for comments.
编辑:现在使它线程安全,感谢您的评论。
public class Logger
{
private static object syncRoot = new Object();
private static Logger instance=null;
// private constructor
private Logger()
{
}
/// <summary>
/// Gets an instance with default parameters based upon the caller
/// </summary>
/// <returns></returns>
public static Logger GetInstance()
{
// make sure you return single instance
if (instance == null)
{
lock (syncRoot)
{
instance=new Logger();
}
}
return instance;
}
}
Hope this helps
希望这可以帮助
回答by roken
The provided statement does not refer to a bottleneck. Declaring your logger in a base class limits the control you have over the logging in derived classes. If you have classes A and B deriving from the same logger-containing base class, you are stuck with the same logging settings for all logging done in classes A and B.
提供的语句没有提到瓶颈。在基类中声明记录器会限制您对派生类中的日志记录的控制。如果您的 A 类和 B 类派生自同一个包含记录器的基类,那么对于在 A 类和 B 类中完成的所有日志记录,您将不得不使用相同的日志记录设置。
log4net allows you to configure your loggers based on the class or namespace they are created for, giving you very tight control of what is logged. For example, having class A log at the info level and class B log at the debug level.
log4net 允许您根据创建记录器的类或命名空间来配置记录器,从而对记录的内容进行非常严格的控制。例如,A 类日志记录在信息级别,B 类日志记录在调试级别。
Adding a single line of a code to each class you wish to log things in is a very small burden for the flexibility it provides.
向您希望登录的每个类添加一行代码对于它提供的灵活性来说是一个非常小的负担。
回答by Groo
The post is not specifically telling you to use a different logger in each derivedclass, but instead a different logger per class typein general. You can, but don't have to use a new logger instance in each derived class.
这篇文章并没有特别告诉您在每个派生类中使用不同的记录器,而是通常每个类类型使用不同的记录器。您可以,但不必在每个派生类中使用新的记录器实例。
One way to look at it is that it might be confusing to have two separate loggers instantiated at the same time (because the base one will still exist), especially if you hide the base one using the same logger name. Your base class methods (not overridden) will still reference the base static logger, and overridden ones will use a different one.
一种看待它的方法是同时实例化两个单独的记录器可能会令人困惑(因为基础记录器仍然存在),尤其是如果您使用相同的记录器名称隐藏基础记录器。您的基类方法(未覆盖)仍将引用基本静态记录器,而被覆盖的方法将使用不同的方法。
Also, the article instantiates the logger like this:
此外,文章像这样实例化记录器:
static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType );
while a slightly simpler way might be to use:
而稍微简单的方法可能是使用:
static readonly ILog Log = LogManager.GetLogger(typeof(YourClass));
First of all, it's marked readonly, meaning you won't be able to change the field accidentally, once initialized. And using the type will work the same way as with reflection, but slightly faster (resolved at compile time). Visual Studio will also update the class name automatically if you choose to rename it (which it wouldn't it you used the string overload).
首先,它被标记为readonly,这意味着一旦初始化,您将无法意外更改该字段。使用该类型的工作方式与反射相同,但速度稍快(在编译时解决)。如果您选择重命名,Visual Studio 还将自动更新类名(如果您使用字符串重载,则不会)。
回答by Richard Schneider
Common practice is to have one logger per class, NOT base class. This way you can enable/disable logging on a per class basis.
通常的做法是每个类有一个记录器,而不是基类。通过这种方式,您可以在每个类的基础上启用/禁用日志记录。
I might also suggest looking at using Common Logging 2.0, http://netcommon.sourceforge.net/.
我可能还建议考虑使用 Common Logging 2.0,http://netcommon.sourceforge.net/。
There are a variety of logging implementations for .NET currently in use, log4net, Enterprise Library Logging, NLog, to name the most popular. The downside of having differerent implementation is that they do not share a common interface and therefore impose a particular logging implementation on the users of your library.
Common.Logging library introduces a simple abstraction to allow you to select a specific logging implementation at runtime. Thus you can defer the decision what particular logging library to use until deployment. Adapters are used for plugging a particular logging system into Common.Logging.
目前正在使用的 .NET 有多种日志记录实现,log4net、企业库日志记录、NLog 等最流行。具有不同实现的缺点是它们不共享公共接口,因此对库的用户强加了特定的日志记录实现。
Common.Logging 库引入了一个简单的抽象,允许您在运行时选择特定的日志记录实现。因此,您可以推迟决定使用哪个特定的日志库,直到部署。适配器用于将特定的日志系统插入 Common.Logging。
回答by Lee Willis
I use a static dictionary in the base class, keyed on type name:
我在基类中使用静态字典,键入类型名称:
private static readonly Dictionary<string, ILog> _loggers = new Dictionary<string, ILog>();
With a method (on the base class) to return a logger:
使用方法(在基类上)返回记录器:
private ILog GetLogger(){
var tn = this.GetType().FullName;
if (!_loggers.ContainsKey(tn)) {
_loggers.Add(tn,LogManager.GetLogger(this.GetType()));
}
return _loggers[tn];
}
I also have the logging methods on the base class:
我在基类上也有日志记录方法:
public void Log(string msg, params object[] args) {
GetLogger().InfoFormat(msg, args);
}
I assume that this would allow me to configure logging per type (although I don't do that) and the GetLogger method could be exposed to derived classes so they can do their own logging.
我认为这将允许我为每种类型配置日志记录(尽管我不这样做)并且 GetLogger 方法可以公开给派生类,以便他们可以进行自己的日志记录。

