1

我在各种项目中发现的一个非常常见的日志记录目标是,任何创建日志条目的类/对象都会将其自己的类/对象名称记录到该条目中。如果日志条目用于异常和堆栈跟踪,则免费包含该信息。但是如果日志条目不是异常的,那么通常会使用各种其他方法来获得这个结果:

  1. 将 const 字段硬编码到每个类中,其中包含类的名称(或记录器本身!)。记录器在记录时被赋予该常量。
  2. 记录器用反映调用堆栈的代码包装,以确定哪个类进行了记录调用。然后将该名称添加到日志条目中。
  3. 每个类都注入了一个记录器实例,该实例已经知道注入它的类的名称。

#3 的一个简单示例如下所示:

ILogger logger = new MyLogger("AmazingClass");
IAmazingClass foo = new AmazingClass(logger);

我想知道的是,是否有任何 IOC 容器,尤其是 Unity,能够优雅地帮助解决这个“场景 #3”?如果是,如何?

我觉得答案应该很简单:IOC 容器“知道”它将构建和注入哪个类,并在完成解析类型之前将“依赖者”信息提供给“依赖者”。

例如,也许 Unity 可以通过委托注册和“反向反射”注册来实现这一点,如下所示:

var container = new UnityContainer();
container.RegisterType<ILogger, MyLogger>(new InjectionFactory(
    (Type targetOfInjection) => new MyLogger(targetOfInjection.Name)
);

我编造了那个语法,但它是完全可信的。也就是说,Unity(或另一个 IOC 容器)实际上为提议的功能提供了什么?

ps我个人对我的记录器和日志记录“没问题”,不会尝试捕获非异常条目的类/对象名称。使代码更简单。但如果我被迫采用这种方法,我通常会采用堆栈反射选项(场景 #2)。当人们也需要在非异常日志记录语句中捕获类名时,了解人们喜欢哪些其他方法会很有趣。然而,最终,这个问题集中在使用 IOC 容器上。

4

1 回答 1

1

也就是说,Unity(或另一个 IOC 容器)实际上为提议的功能提供了什么?

我无法回答 Unity 的问题,但使用Simple Injector,您可以按如下方式注册:

container.RegisterWithContext<ILogger>(context =>
    new MyLogger(context.ImplementationType.Name));

您需要使用Simple Injector 文档中 Advanced Scenarios 部分中的此代码片段RegisterWithContext添加扩展方法。最大的优点是使用 Simple Injector,即使是这种基于上下文的注册也能以极快的速度解决。

但请注意,基于上下文的注入通常是一种设计味道。您在现场随处可见这种模式的事实并不能说明它是正确的。因此,在您继续之前,请确保您没有记录太多,并且您的应用程序设计遵循 SOLID 原则

于 2013-03-18T18:26:16.943 回答