在C#中,我的Common.Logging记录器应该是实例成员还是静态成员? [英] In C# should my Common.Logging logger be an instance member or static?

查看:321
本文介绍了在C#中,我的Common.Logging记录器应该是实例成员还是静态成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

寻找使用 Common.Logging ,我注意到某些类将记录器实例声明为类的静态成员.例如:

Looking a project that uses Common.Logging for .NET, I noticed that some classes declare the logger instance as a class static member. For instance:

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")));
    }
}

在其他类中,记录器被声明为实例成员:

And in other classes the logger is declared as an instance member:

public class SimpleExample : IExample
{
    public virtual void Run()
    {
        ILog log = LogManager.GetLogger(typeof (SimpleExample));

        log.Info("------- Initializing ----------------------");

        // etc
    }
}    

是否有理由偏爱一种方法或另一种方法?

Is there a reason to prefer one approach or the other?

在哪种情况下,建议使用每种方法?与线程安全有关吗?

In which cases is each approach recommended? Is it related to thread safety?

如果我只声明一个带有静态"logger"成员的"Logger"类,并且整个项目都使用了它(除了我实际上会拥有一个全局变量的问题),这会是一个问题吗?

Would it be a problem if I just declared a "Logger" class with a static "logger" member and the whole project used that (apart from the issue that I would in practice have a global variable)?

推荐答案

大多数记录器都是线程安全的,并且在时间和内存方面,创建它们的实例的开销很少.因此,真正的问题应该是从编程和可维护性的角度来看什么才有意义.

Most loggers are thread safe, and creating instances of them has very little overhead, both in terms of time and memory. So the real question needs to be what makes sense from a programming and maintainability standpoint.

一方面,由于记录器在概念上是与您的 class 绑定的,而不是与该类的 instance 绑定的,因此很多人都希望保持静态.这是一个完全正确的论点.例如,如果HelloWorldJob扩展了HelloJob,我想大多数人都希望由HelloJob中的代码编写的日志消息绑定到HelloJob类,即使您有更具体的子类实例.能够从静态方法访问记录器也很好,如果不在静态字段中,则不可能.

On the one hand, since the logger is conceptually tied to your class, and not to the instance of the class, a lot of people prefer to keep it static. That's a perfectly valid argument. For example, if HelloWorldJob extends HelloJob, I think most people would expect the log message written by code in HelloJob to be tied to the HelloJob class, even though you have a more specific subclass instance. It's also nice to be able to access your logger from static methods, which wouldn't be possible if it's not on a static field.

另一方面,您的HelloJob没有理由应负责获取其自己的记录器实例.使用依赖注入代替有很多说法(单元可测试性,其他可配置性和更简单的代码).因此,我个人建议您的记录器由DI框架注入,在这种情况下,需要在每个实例字段中引用它.

On the other hand, there is no reason that your HelloJob should be responsible for getting its own logger instance. There's a lot to be said for using dependency injection instead (unit testability, additional configurability, and simpler code). So I personally suggest having your logger injected by a DI framework, in which case it would need to be referenced on a per-instance field.

public class HelloJob : IJob
{
    private readonly ILog _log;

    public HelloJob(ILog log)
    {
        _log = log;
    }
    ...
}

您的DI框架可以根据运行时知道的详细信息来设置记录器,或者您可以在单元测试中提供伪造的或模拟的记录器,以确保生成预期的日志消息.请注意,即使您引用的是每个实例的字段,您仍然可以完全自由地使用每个类(甚至是一个单例)的实例-这些只是细节,不需要成为此类的一部分关注.

Your DI framework can set up the logger based on details it knows at run-time, or you can provide a fake or mocked logger in your unit tests to make sure the expected log messages are produced. Note that even though you are referring to a per-instance field, you're perfectly free to still use a per-class (or even a singleton) instance--those are just details that don't need to be part of this class's concern.

随着时间的流逝,我对使用静态记录器的方向有了更多的转变.更具体地说,我真的很喜欢使用 Fody Anotar 库来生成用于我,所以我只需要在源代码中编写日志记录语句,例如:

Over time I've shifted my opinion more in the direction of using a static logger. More specifically, I really like using Fody Anotar libraries to generate the static logger (and other helpful code) for me, so all I have to write in my source code is logging statements like:

LogTo.Info("This is a message");

这篇关于在C#中,我的Common.Logging记录器应该是实例成员还是静态成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆