你看到的是两个宇宙碰撞;两个 DI 库对 transient 的含义都有自己的、不兼容的定义:
- Simple Injector 认为具有
Transient 生活方式的组件是短暂的,或简短。这就是 Simple Injector 不允许将瞬态注入作用域组件的原因。作用域的寿命可能比被视为简短的要长得多。
- ASP.NET Core 并不认为瞬态组件是短暂的根本。相反,.NET Core 中
Transient 组件的预期生命周期与其使用者的预期生命周期一样长。 docs 甚至声明“此生命周期最适合轻量级、无状态的服务。”
更新 在 Simple Injector v5 中,这种行为有所放松,现在(默认情况下)可以将瞬态注入到作用域组件中。然而,瞬态含义的定义保持不变,这意味着当您尝试将瞬态注入单例时,Simple Injector 仍然认为这是一个错误。
正是由于这种行为,Microsoft.Extensions.DependencyInjection (MS.DI) 容器允许将瞬态注入到单例和作用域消费者中。
我什至会争辩说,微软错误地命名了他们的生活方式,因为实际行为是每个消费者的依赖项都有一个实例。微软似乎从 Autofac 复制了这种行为。然而,Autofac 确实将这种生活方式命名为 InstancePerDependency,如果你问我,这是一个更明显的名字。
不过,奇怪的是微软的 AddLocalization 扩展方法 registers StringLocalizer<T> 是暂时的。这很奇怪,因为除了包裹的IStringLocalizer,StringLocalizer<T> 没有任何状态。不仅如此,它包装的IStringLocalizer 是由注入的IStringLocalizerFactory 产生的,并且可以预期是同一个实例(这是由ResourceManagerStringLocalizerFactory caches 返回的实例这一事实强制执行的)。
如上所述,在 MS.DI 中,Transient 表示“我将与我的消费者一样长寿。 “这实际上意味着StringLocalizer<T> 实例可以与单例一样长,这意味着:在整个应用程序的持续时间内。
从这方面来看,本地化团队选择StringLocalizer<T> 来拥有短暂的生活方式实际上真的很奇怪,即使在 MS.DI 中也是如此。瞬态仅意味着创建了更多实例,并且IStringLocalizerFactory 的调用频率高于所需。我发现Singleton 的注册方式更加明显。
长话短说,我建议覆盖使用单例的默认注册,因为无论如何这样做是安全的:
services.AddLocalization();
services.AddSingleton(typeof(IStringLocalizer<>), typeof(StringLocalizer<>));