C#:ILogger与静态日志实例

时间:2018-07-22 08:43:46

标签: c# logging architecture

这是一个体系结构问题: 您是使用ILogger(并通过DI将其传递给构造函数)还是更喜欢静态类Log?

我们经常使用ILogger,但它确实使代码混乱,尤其是在通过构造函数传递代码时。如果不是通过构造函数传递,而是每次都创建,那么使用接口真的看不到任何好处。

那么您如何处理呢?我对它背后的论点特别感兴趣-不仅仅是说“静态”或“接口”。

Thx

2 个答案:

答案 0 :(得分:1)

使用静态任何实例都是一个坏主意,这取决于您的用例。
-在单元测试中很难模拟它们,因此即使不需要它们,记录器也总是在写日志。
-缺乏模拟还意味着您无法编写测试以确保在适当情况下编写了错误日志。 -无法在运行时替换它们,以允许注入不同的记录器。如果要发布库供他人使用,这可能很重要。我定义了一个标准的记录器接口,并将所有内容记录到该接口,然后允许客户端注入自己的记录器,只要它实现了我的界面即可。
-如果使用供应商提供的默认静态日志实现,则您将被锁定在其界面中,这意味着您无法隐藏或更改记录器的表面积。如果新记录器的语法发生更改,则更改记录器将变得更加费劲。

因此,您可以进行某种注射。就我个人而言,我更喜欢在构造函数中具有所有依赖关系,即使它变得冗长,因为很容易看到特定类具有的所有依赖关系。如果您要避免使用大型构造函数,则可以研究属性注入。这需要在类的属性上具有属性,但仍具有注入依赖项的所有优点。如果将注入的属性放在基类上,它将自动对所有子级可用。

顺便说一句,我不喜欢上述环境上下文,因为它基本上是一个单一用途的DI容器,并且您必须具体引用多个环境服务容器。如果可以轻松访问此模式,请考虑“服务位置”,它是相同的想法,但更灵活。

答案 1 :(得分:0)

如果ILogger确实是一个跨领域的关注点,并且在每个地方都被使用,从而导致使用新的构造函数参数污染每个实例,那么您需要的是使用一种特殊的依赖项注入方式,即AmbientContext

基本上,它为您提供了一个单例Context属性,可以从业务范围内的任何位置访问该属性,并包含“全局”依赖项,例如日志记录,时间服务等,随您所需。

但是请注意,这并不意味着您可以扔掉ILogger并使用带有硬编码实现的静态Log类。环境上下文也是依赖注入的一种方式,因此应解决其依赖。