随着RegisterWithContext
扩展方法中,您注册一个谓词,允许您使用有关使用组件的信息构建实例。该信息由扩展方法提供给谓词。
因为这意味着您可以为每个消费类型构建一个完全不同的实例,使注册除了瞬态之外的任何其他内容都可能导致非常奇怪的行为。想象一下,例如注册一个ILogger
抽象,你可以在其中创建一个Logger<T>
实施其中T
是消费组件的类型:
container.RegisterWithContext(c =>
(ILogger).container.GetInstance(
typeof(Logger<>).MakeGenericType(c.ImplementationType)));
如果您将此注册设为单例,即使使用组件是单例,也会导致问题,因为相同的实例将被注入到每个使用者中;而每个消费者都需要自己的实例,因为他们需要自己的封闭通用版本,即:Logger<Consumer1>
, Logger<Consumer2>
, Logger<Consumer3>
相反,每个消费者都会获得相同的实例;为第一个解析的消费者创建的实例。这显然是很糟糕的。
使用 Scoped 实例时也会存在同样的问题;您将在范围持续时间内获得相同的实例,这通常不是您想要的;该实例应该依赖于上下文。
这是一个严重的限制RegisterWithContext
Simple Injector v2 文档提供的扩展方法。由于这太有限了,Simple Injector v3 现在包含一个内置的RegisterConditional
方法取代了RegisterWithContext
扩展方法。 v3 文档从未提及RegisterWithContext
不再,我们建议使用RegisterWithContext
反而。
文档描述 https://simpleinjector.readthedocs.io/en/latest/advanced.html#context-based-injection如何使用RegisterConditional
并显示以下示例:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
由于此注册的谓词返回true
,注册并不是真正有条件的,而只是上下文相关的。
使用此代码您可以返回Logger<T>
特定于消费组件,但仍确保每个关闭的组件最多有一个实例Logger<T>
类型;因此是一个单身人士。
与新版的主要区别RegisterConditional
和旧的RegisterWithContext
是您无法提供工厂委托来创建实例。和RegisterConditional
,Simple Injector 控制实例(而不是您的委托)的创建,这允许类型的创建完全合并到管道中,并允许 Simple Injector 验证和诊断已注册的组件及其依赖项。