ContextDependent实例作为Simple Injector中的Singleton [英] ContextDependent instance as Singleton in Simple Injector

查看:41
本文介绍了ContextDependent实例作为Simple Injector中的Singleton的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 SimpleInjector 库的 ContextDependentExtensions 有疑问.我们具有以下扩展名,可以在某些上下文中向注入器中添加元素以添加可能性:

这里是一个兴趣线:应该总是短暂的!

那是什么意思?我们可以在这里使用 Lifestyle.Singleton Lifestyle.Scoped 生活方式吗?

有人可以帮我解释一下吗?预先感谢.

解决方案

使用 RegisterWithContext 扩展方法,您将注册一个谓词,该谓词允许您使用有关使用方组件的信息来构建实例.该信息通过扩展方法提供给谓词.

因为这意味着您可以为每种使用类型建立一个完全不同的实例,因此除了瞬态注册外,其他任何事情都可能导致非常奇怪的行为.例如,想像一下 ILogger 抽象的注册,您在其中创建 Logger< T> 实现,其中 T 是使用组件的类型:

  container.RegisterWithContext(c =>(ILogger).container.GetInstance(typeof(Logger<> .MakeGenericType(c.ImplementationType))); 

如果使该注册单例,即使使用组件是单例的,也将导致问题,因为会将相同的实例注入每个使用者.而每个使用者都需要自己的实例,因为他们需要自己的封闭通用版本,即: Logger< Consumer1> Logger< Consumer2> Logger<Consumer3> 等.相反,非常消费者将获得相同的实例.为第一个解析的使用者创建的实例.这显然很糟糕.

使用范围实例时,也会存在相同的问题;在作用域的持续时间内,您将获得相同的实例,通常这不是您想要的;该实例应与上下文相关.

这是Simple Injector v2文档随附的 RegisterWithContext 扩展方法的严重限制.由于此限制太大,因此Simple Injector v3现在包含内置的 RegisterConditional 方法,该方法代替了 RegisterWithContext 扩展方法.v3文档不再引用 RegisterWithContext ,我们建议改用 RegisterWithContext .

文档描述如何使用 RegisterConditional 并显示以下示例:

  container.RegisterConditional(typeof(ILogger),c =>typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),生活方式.Singleton,c =>真的); 

由于此注册的谓词返回 true ,因此该注册实际上并不是有条件的,而只是上下文的.

使用此代码,您可以返回特定于使用组件的 Logger< T> ,但仍要确保每个封闭的 Logger< T> 类型;因此是单身人士.

新的 RegisterConditional 与旧的 RegisterWithContext 之间的主要区别在于,您无法提供工厂委托来创建实例.使用 RegisterConditional ,Simple Injector可以控制实例的创建(而不是您的委托),这可以将类型的创建完全整合到管道中,并允许Simple Injector验证和诊断已注册的组件及其依赖项.

I have a question regarding ContextDependentExtensions of SimpleInjector library. We have the following extension to add possibility adding elements into injector with some context: ContextDependentExtensions

Example:

var container = new Container();
container.RegisterWithContext(logger => new SimpleLogger("Logger Constructor Parameter"));

Here is one interest line: Should always be transient!

So, what does it mean? And can we use here Lifestyle.Singleton or Lifestyle.Scoped lifestyle?

Can someone explain it for me? Thanks in advance.

解决方案

With the RegisterWithContext extension method, you register a predicate that allows you to build up an instance using the information about the consuming component. This information is supplied to the predicate by the extension method.

Since this means that you can built up a completely different instance per consuming type, making the registration anything else but transient, could lead to very weird behavior. Imagine for instance the registration of an ILogger abstraction where you create a Logger<T> implementation where the T is the type of the consuming component:

container.RegisterWithContext(c =>
    (ILogger).container.GetInstance(
        typeof(Logger<>).MakeGenericType(c.ImplementationType)));

If you would make this registration singleton, this would cause problems, even if the consuming components are singleton, because the same instance would be injected into each consumer; while each consumer would require their own instance, because they require their own closed-generic version, namely: Logger<Consumer1>, Logger<Consumer2>, Logger<Consumer3>, etc. Instead, very consumer would get the same instance; the instance that was created for the first resolved consumer. This is obviously awful.

This same problem will exist as well when using Scoped instances; you'll get the same instance for the duration of the scope, which is typically not what you want; the instance should be context dependent.

This is a serious limitation of the RegisterWithContext extension method that was supplied with the Simple Injector v2 documentation. Since this was too limiting, Simple Injector v3 now contains a built-in RegisterConditional method that replaces the RegisterWithContext extension method. The v3 docs never refer to RegisterWithContext anymore and we would advice to use RegisterWithContext instead.

The documentation describes how to use the RegisterConditional and shows the following example:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

Since the predicate of this registration returns true, the registration isn't really conditional, but simply contextual.

Using this code you can return a Logger<T> specific to the consuming component, but still ensure that there is at most one instance of each closed Logger<T> type; thus a singleton.

The main difference between the new RegisterConditional and the old RegisterWithContext is that you can't supply a factory delegate to create instances. With RegisterConditional, Simple Injector is in control over the creation of instances (instead your delegate) and this allows the creation of types to be completely incorporated in the pipeline and allows Simple Injector to verify and diagnose the registered component and its dependencies.

这篇关于ContextDependent实例作为Simple Injector中的Singleton的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆