反映注射目标
本文关键字:目标 | 更新日期: 2023-09-27 18:04:27
我在各种项目中发现的一个非常常见的日志目标是,任何创建日志条目的类/对象都将自己的类/对象名称记录到该条目中。如果日志条目是用于异常和堆栈跟踪的,则免费包含该信息。但是,如果日志条目不是针对异常,则通常使用各种其他方法来获得此结果:
- 在每个类中硬编码一个const字段,它包含类的名称(或记录器本身!)当日志记录时,记录器被赋予const。
- 日志记录器用反映调用堆栈的代码包装,以确定哪个类进行了日志调用。然后将名称添加到日志条目中。
- 每个类被注入一个logger实例,该实例已经知道被注入的类的名称。
#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容器)实际上提供了什么功能?
注。我个人认为我的日志记录器和日志记录没有尝试捕获非异常条目的类/对象名称。使代码更简单。但是,如果我被迫采用这种方法,我通常会选择堆栈反射选项(场景#2)。当需要在非异常日志记录语句中捕获类名时,了解人们喜欢的其他方法是很有趣的。然而,这个问题最终集中在使用IOC容器上。
也就是说,Unity(或其他IOC容器)实际上提供了什么对于提议的能力?
我不能回答Unity的问题,但是使用Simple Injector,你可以这样注册:
container.RegisterWithContext<ILogger>(context =>
new MyLogger(context.ImplementationType.Name));
你需要使用以下代码片段添加RegisterWithContext
扩展方法,这些代码片段来自简单注入器文档中的高级场景一节。简单注入器的一大优点是,即使这种基于上下文的注册也能以极快的速度解决。
但是请注意,基于上下文的注入通常是一种设计气味。事实上,你在这个领域里随处可见这种模式,并不意味着它是正确的。因此,在继续之前,请确保您没有记录太多日志,并且您的应用程序设计遵循SOLID原则。