寻找 a project使用 Common.Logging对于.NET,我注意到一些类将记录器实例声明为类静态成员。例如:
public class HelloJob : IJob
{
private static ILog _log = LogManager.GetLogger(typeof(HelloJob));
public HelloJob()
{
}
public virtual void Execute(IJobExecutionContext context)
{
_log.Info(string.Format("Hello World! - {0}", System.DateTime.Now.ToString("r")));
}
}
而在其他类中,记录器被声明为实例成员:
public class SimpleExample : IExample
{
public virtual void Run()
{
ILog log = LogManager.GetLogger(typeof (SimpleExample));
log.Info("------- Initializing ----------------------");
// etc
}
}
是否有理由偏爱其中一种方法?
在哪些情况下推荐每种方法?跟线程安全有关吗?
如果我只是声明一个带有静态“记录器”成员的“记录器”类并且整个项目都使用它(除了我在实践中会有一个全局变量的问题),这会不会有问题?
最佳答案
大多数记录器都是线程安全的,创建它们的实例在时间和内存方面的开销很小。因此,真正的问题应该是从编程和可维护性的角度来看什么是有意义的。
一方面,由于记录器在概念上与您的类相关联,而不是与类的实例相关联,因此很多人更喜欢将其保持静态.这是一个完全有效的论点。例如,如果 HelloWorldJob
扩展 HelloJob
,我想大多数人会期望 HelloJob
中的代码写入的日志消息与 相关联>HelloJob
类,即使您有一个更具体的子类实例。能够从静态方法访问您的记录器也很好,如果它不在静态字段上,这是不可能的。
另一方面,您的 HelloJob 没有理由负责获取自己的记录器实例。有很多关于使用依赖注入(inject)的说法(单元可测试性、额外的可配置性和更简单的代码)。因此,我个人建议让您的记录器由 DI 框架注入(inject),在这种情况下,需要在每个实例字段上引用它。
public class HelloJob : IJob
{
private readonly ILog _log;
public HelloJob(ILog log)
{
_log = log;
}
...
}
您的 DI 框架可以根据它在运行时知道的详细信息设置记录器,或者您可以在单元测试中提供伪造或模拟的记录器以确保生成预期的日志消息。请注意,即使您指的是每个实例字段,您仍然可以完全自由地使用每个类(甚至是单例)实例——这些只是不需要成为此类的一部分的细节关注。
更新
随着时间的推移,我的观点更多地转向了使用静态记录器的方向。更具体地说,我真的很喜欢使用 Fody Anotar库为我生成静态记录器(和其他有用的代码),所以我必须在我的源代码中写的是记录语句,如:
LogTo.Info("This is a message");
关于c# - 在 C# 中,我的 Common.Logging 记录器应该是实例成员还是静态的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13713930/