如果使用日志外观,在使用IoC / DI时是否应注入日志记录基础结构?

时间:2012-09-25 22:20:42

标签: .net logging dependency-injection inversion-of-control

我正在使用Autofac作为我的IoC,并且从我读过的关于DI主题的所有内容中使用“构造函数注入”来显式地暴露类依赖... 但是,我也在使用日志外观(Common.Logging)和Log4Net,并创建了Autofac模块来注入它。 现在,在我想要进行一些日志记录的每个类中,我都有额外的构造函数参数(参见示例#1)....

我想知道在使用日志门面时是否需要记录DI? 我知道通过构造函数签名显式公开依赖是一个很好的架构。 如果是登录外观我相信以下是真的:

  • 我仍然可以随时“更换”日志框架
  • IMHO课程并不真正依赖Logger。如果未配置日志记录,则使用NullLogger。它几乎是“如果你需要的话就是它”,而“除非你提供它,否则它将不起作用”这种交易...(参见样本#2)

那么,别人怎么想?注入伐木门面是否过度杀伤? 关于这个主题有一些similar questions但是更笼统地说(infrastructure) - 我主要对记录感兴趣....

// IoC "way"
public class MyController : BaseController
{
    private readonly ILog _logger;

    public MyController(ILog logger)
    {
        _logger = logger;
    }

    public IList<Customers> Get()
    {
        _logger.Debug("I am injected via constructor using some IoC!");
    }
}

// just use the logger "way"
public class MyController : BaseController
{
    private static readonly ILog Logger = LogManager.GetCurrentClassLogger();

    public IList<Customers> Get()
    {
        Logger.Debug("Done! I can use it!");
    }
}

5 个答案:

答案 0 :(得分:29)

记录只是基础设施。注射它是矫枉过正的。我个人甚至不使用抽象层。我使用库直接提供的静态类。我的动机是,我不太可能在当前项目中切换日志库(但可能会切换到下一个项目)。

但是,您在示例中使用的是控制器。你为什么需要登录?控制器只是视图和模型(业务逻辑)之间的适配器。应该没有必要登录。

您通常只登录包含业务逻辑的类,并在顶层执行以便能够记录未处理的异常。这些是调试的难点,因此也是需要记录的地方。

必须在其他地方登录表示您需要重构以正确封装您的业务逻辑。

答案 1 :(得分:18)

这可能是一篇较老的帖子,但我想加入。

日志记录系统的IOC过度使用的想法是短视的。

日志记录是一种机制,应用程序开发人员可以通过该机制与其他系统(事件日志,平面文件,数据库等)进行通信,并且这些内容现在都是应用程序所依赖的外部资源。

如果我的单元测试代码现在已锁定到特定记录器,我应该如何对组件的日志记录进行单元测试?分布式系统通常使用记录器来记录源,而不是文件系统上的平面文件。

向我注入记录器与注入数据库连接API或外部Web服务没有什么不同。它是应用程序所需的资源,因此应该注入,因此您可以测试组件对所述资源的使用情况模拟所述依赖性的能力,以独立于日志记录接收者来测试我的组件的输出,对于强单元测试。

鉴于IOC容器使得这样的注射成为孩子的游戏,在我看来,不使用IOC来注入记录器并不是一种有效的方法。

答案 2 :(得分:4)

  

现在,在我想要做一些日志记录的每个班级中,我都有额外的   构造函数参数

如果您需要在系统中记录许多类,那么您的设计就会出现问题。要么你记录太多,要么你违反了单一责任原则,因为记录是一个贯穿各领域的问题,你不应该把你的课程弄得像日志这样的跨界问题。

半年前我回答了一个(完全不同的)问题,我的回答适用于你的问题。请阅读this

答案 3 :(得分:2)

我个人认为这太过分了。

理想情况下,日志记录的开销非常低,因此每个类的单个静态记录器实例似乎是更好的解决方案。保持低开销可以促进使用调试级别的日志记录进行检测。

答案 4 :(得分:0)

在许多应用程序中,由于需要在整个应用程序的体系结构中进行日志记录,因此将日志注入到各处都会使代码变得混乱和复杂。只要您的Logger具有某种Logger机制,并为运行环境附加日志服务,就可以静态引用Attach(ILoggerService)对象。然后,您的静态Logger将它们存储在一个集合中,以便在执行记录命令时使用。

在运行时引导应用程序时,请附加应用程序所需的日志记录目标(文件,数据库,Web服务等)。

执行自动测试时,可以通过不附加任何内容来选择不使用日志记录(默认情况下)。如果要分析被测系统的日志记录,请在设置测试时附加自己的ILoggerService实例/替代/模拟。

诸如此类的静态Logger应该具有最小的性能问题,并且不会产生意想不到的后果,同时避免了依赖注入的需要,从而避免了代码混乱。

必须指出,您不应该对体系结构中的每个对象都采用这种静态对象方法。日志记录是一个特例。通常,在代码库中使用静态对象会使维护和测试变得困难,应该避免。