我在各种项目中发现的一个非常常见的日志记录目标是,任何创建日志条目的类/对象都会将其自己的类/对象名称记录到该条目中。如果日志条目用于异常和堆栈跟踪,则免费包含该信息。但是如果日志条目不是异常的,那么通常会使用各种其他方法来获得这个结果:
- 将 const 字段硬编码到每个类中,其中包含类的名称(或记录器本身!)。记录器在记录时被赋予该常量。
- 记录器用反映调用堆栈的代码包装,以确定哪个类进行了记录调用。然后将该名称添加到日志条目中。
- 每个类都注入了一个记录器实例,该实例已经知道注入它的类的名称。
#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 容器上。