简单的喷油器装饰,具有额外的依赖性
本文关键字:依赖性 简单 | 更新日期: 2023-09-27 17:57:07
>我有一个装饰器SomethingLoggerDecorator
,应该用日志记录来装饰ISomething
实例:
public class SomethingLoggerDecorator : ISomething
{
private readonly ISomething decoratee;
private readonly ILogger logger;
public SomethingLoggerDecorator(ISomething decoratee, ILogger logger)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void DoSomething()
{
this.logger.Info("Doing Something");
this.decoratee.DoSomething();
}
public void DoSomethingElse(string withThis)
{
this.logger.Info("Doing Something Else with " + withThis);
this.decoratee.DoSomethingElse(withThis);
}
}
如何使用简单注入器用SomethingLoggerDecorator
装饰ISomething
实例,并使用静态工厂方法将ILogger
实例注入到每个装饰器中LogManager.GetLogger(decoratee.GetType())
其中装饰者是要修饰的实际实例?此外,注塑ILogger
和SomethingLoggerDecorator
的使用寿命应始终与装饰者的使用寿命相匹配。
在Simple Injector中有多种方法可以做到这一点。
首先,你可以让装饰器的构造函数依赖于DecoratorContext类。DecoratorContext
包含有关修饰器的上下文信息。它包含诸如包装装饰器的类型和修饰的实际实现的类型(实际实例)等信息。因此,您的装饰器可能如下所示:
public class SomethingLoggerDecorator : ISomething
{
private readonly ISomething decoratee;
private readonly DecoratorContext context;
public SomethingLoggerDecorator(ISomething decoratee, DecoratorContext context)
{
this.decoratee = decoratee;
this.context = context;
}
public void DoSomething()
{
var logger = LogManager.GetLogger(this.context.ImplementationType);
logger.Info("Doing Something");
this.decoratee.DoSomething();
}
}
使用此DecoratorContext
类的缺点是,您的装饰器需要依赖于简单注入器,这基本上意味着您必须将装饰器移动到组合根中,以防止您的应用程序依赖于 DI 库。您可以在此处找到有关使用此DecoratorContext
类的更多信息。
另一种选择是使您的装饰器通用,并为可以制造正确装饰器的RegisterDecorator
重载之一提供装饰器类型工厂。例如:
public class SomethingLoggerDecorator<TImplementation> : ISomething
{
private readonly ISomething decoratee;
public SomethingLoggerDecorator(ISomething decoratee)
{
this.decoratee = decoratee;
}
public void DoSomething()
{
var logger = LogManager.GetLogger(typeof(TImplementation));
logger.Info("Doing Something");
this.decoratee.DoSomething();
}
}
或者可选:
public class SomethingLoggerDecorator<TImplementation> : ISomething
{
private readonly ISomething decoratee;
private readonly ILogger<TImplementation> logger;
public SomethingLoggerDecorator(ISomething decoratee, ILogger<TImplementation> logger)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void DoSomething()
{
this.logger.Info("Doing Something");
this.decoratee.DoSomething();
}
}
使用这两种实现,您可以按如下方式注册装饰器:
container.RegisterDecorator(typeof(ISomething),
c => typeof(SomethingLoggerDecorator<>).MakeGenericType(c.ImplementationType),
Lifestyle.Transient,
predicate: c => true);
使用第二个实现,您将问题稍微移动到泛型ILogger<T>
抽象,但实现可能如下所示:
public class Log4netAdapter<T> : ILogger<T>
{
public void Log(LogEntry entry) {
var logger = LogManager.GetLogger(typeof(T));
// TODO: log
}
}