我使用Simple Injector作为我的IoC容器。我想根据执行范围的存在注入我的类记录器。应该有一个默认记录器(单例)和其他基于我的上下文。
我尝试过这样的事情:
container.RegisterConditional(typeof(ILogger),
x => typeof(NContextLogger<>).MakeGenericType(x.Consumer.ImplementationType),
Lifestyle.Scoped,
x => container.GetCurrentExecutionContextScope() != null);
container.RegisterConditional(typeof(ILogger),
x => typeof(NLogger<>).MakeGenericType(x.Consumer.ImplementationType),
Lifestyle.Singleton,
x => container.GetCurrentExecutionContextScope() == null);
问题在于创建NContextLogger<>
的任何实例。因为当它创建单身的NLogger<>
时,simpleinjector不会尝试创建NContextLogger
的实例。
答案 0 :(得分:2)
提供给RegisterConditional
的谓词不能用于运行时决策,因为谓词的结果被缓存并刻录到表达式树和已编译的委托中。然而, GetCurrentExecutionContextScope()
Lifestyle.Scoped.GetCurrentScope(Container)
的可用性是运行时决定。
在构造对象图时,不应该根据运行时条件做出决定(出于与runtime data shouldn't be injected into components相同的原因)。
不是在构建对象图的过程中根据运行时条件做出决策,而是应该推迟这些决策,直到构建对象图之后。最明显的方法是引入代理类:
public sealed class ProxyLogger<T> : ILogger
{
private readonly Container container;
public ProxyLogger(Container container) {
this.container = container;
}
// Implement ILogger method(s)
public void Log(string message) => Logger.Log(message);
private ILogger Logger => Lifestyle.Scoped.GetCurrentScope(container) == null
? container.GetInstance<NLogger<T>>()
: container.GetInstance<NContextLogger<T>>();
}
使用此代理类,您可以进行以下注册以满足您的要求:
container.RegisterConditional(typeof(ILogger),
c => typeof(ProxyLogger<>).MakeGenericType(x.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
container.Register(typeof(NLogger<>), typeof(NLogger<>), Lifestyle.Singleton);
container.Register(typeof(NContextLogger<>), typeof(NContextLogger<>),Lifestyle.Singleton);