MiF*_*vil 13 c# dependency-injection startup asp.net-core
我注意到在一些.net核心示例中有调用 TryAddSingleton
,有些是 AddSingleton
在注册服务时.
如果服务类型尚未注册,则反编译器会显示TryAdd(由TryAddSingleton调用)将指定的参数"descriptor"添加到"集合".
这是否意味着使用TryAddSingleton总是更安全,以防某些其他方法/库已经注册了同一个类?
Ste*_*ven 28
正如你已经注意到了,之间的区别TryAddSingleton
,并AddSingleton
是AddSingleton
总是附加登记到集合,而TryAddSingleton
只有做到这一点,当存在针对给定服务类型没有注册.
当同一服务类型存在多个注册但请求一个实例时,.NET Core将始终返回最后一个.这意味着行为AddSingleton
是替换非集合解析的实例.例如:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>(); // ‘replaces’ A
IX x = container.GetService<IX>(); // resolves B
Run Code Online (Sandbox Code Playgroud)
但是,对于集合结果,AddSingleton
行为完全不同,因为在这种情况下AddSingleton
表现为该服务类型的现有注册的集合"附加".例如:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>();
IEnumerable<IX> xs = container.GetServices<IX>(); // resolves A and B
Run Code Online (Sandbox Code Playgroud)
随着TryAddSingleton
然而,注册将不会被当已经存在针对给定服务类型注册加入.这意味着,无论何时将服务类型解析为一个实例或实例集合,在至少有一个注册时都不会添加注册.例如:
services.TryAddSingleton<IX, A>(); // adds A
services.TryAddSingleton<IX, B>(); // does not add B, because of A
IX x = container.GetService<IX>(); // resolves A
services.TryAddSingleton <IX, A>(); // adds A
services.TryAddSingleton <IX, B>(); // does not add B, because of A
IEnumerable<IX> xs = container.GetServices<IX>(); // resolves A
Run Code Online (Sandbox Code Playgroud)
TryAddSingleton
对于希望将自己的组件注册到容器的框架和第三方库代码特别有用.它允许应用程序开发人员覆盖框架或库的默认注册,即使应用程序开发人员在AddXXX
调用框架或第三方扩展方法之前注册了该组件.例如:
services.TryAddSingleton<IX, A>(); // adds A
services.AddThirdPartyLibrary (); // calls services.TryAddSingleton <IX, B>();
IX x = container.GetService<IX>(); // resolves A
Run Code Online (Sandbox Code Playgroud)
如果第三方库调用AddSingleton
而不是TryAddSingleton
,应用程序开发人员A
将始终被覆盖,这可能会让开发人员感到困惑.作为应用程序开发人员,您通常知道自己注册了什么,这使得对TryAddSingleton
应用程序开发人员的使用不那么有用.
我甚至认为,从应用程序开发人员的角度来看,行为AddSingleton
可能非常棘手,因为它隐含地覆盖了现有的注册,没有任何警告.我的经验是,这种行为可能导致很难发现配置错误.一个更安全的设计本来就有AddSingleton
,AppendSingleton
以及ReplaceSingleton
方法,如果AddSingleton
存在注册会抛出异常,并且ReplaceSingleton
实际上会丢弃现有的注册.
归档时间: |
|
查看次数: |
3940 次 |
最近记录: |