问题描述
我注意到在某些.net核心示例中,有TryAddSingleton
调用,而在AddSingleton
中有一些注册服务的调用.
I've noticed in some .net core examples there are calls to TryAddSingleton
, and in some AddSingleton
when registering services.
反编译器显示TryAdd(由TryAddSingleton调用)如果尚未注册服务类型,则将指定的参数描述符"添加到集合"中.
Decompiler shows that TryAdd( called by TryAddSingleton)adds the specified param "descriptor" to the "collection" if the service type hasn't been already registered.
如果其他一些方法/库已经注册了相同的类,这是否意味着使用TryAddSingleton总是更安全?
Does it mean that it always safer to use TryAddSingleton, in case if some other method/library already registered the same class?
推荐答案
您已经注意到,TryAddSingleton
和AddSingleton
之间的区别是AddSingleton
总是将注册附加到集合中,而仅TryAddSingleton
如果没有针对给定服务类型的注册,则执行此操作.
As you already noticed, the difference between TryAddSingleton
and AddSingleton
is that AddSingleton
always appends the registration to the collection, while TryAddSingleton
only does this when there exists no registration for the given service type.
当同一服务类型存在多个注册,但请求一个实例时,.NET Core将始终返回最后一个.这意味着AddSingleton
的行为是替换非集合解析的实例.例如:
When multiple registrations exist for the same service type, but one instance is requested, .NET Core will always return the last one. This means that the behavior of AddSingleton
is to replace instances for non-collection resolves. For instance:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>(); // ‘replaces’ A
IX x = container.GetService<IX>(); // resolves B
对于集合解析,AddSingleton
的行为完全不同,因为在这种情况下,AddSingleton
表现为该服务类型已经存在的注册的集合追加".例如:
For collection resolves however, AddSingleton
behaves completely different, because in that case AddSingleton
behaves as a collection ‘append’ of already existing registrations for that service type. For instance:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>();
IEnumerable<IX> xs = container.GetServices<IX>(); // resolves A and B
对于TryAddSingleton
,如果已经存在针对给定服务类型的注册,则不会添加注册.这意味着,与将服务类型解析为一个实例或实例集合的时间无关,当至少有一个注册时,将不会添加注册.例如:
With TryAddSingleton
however, the registration will not be added when there already exist registrations for the given service type. This means that, independently of when a service type is resolved as one instance or as a collection of instances, the registration will not be added when there is at least one registration. For instance:
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
TryAddSingleton
对于希望将其自己的组件注册到容器的框架和第三方库代码特别有用.即使应用程序开发人员在调用框架或第三方AddXXX
扩展方法之前注册了该组件,它也允许应用程序开发人员覆盖框架或库的默认注册.例如:
TryAddSingleton
is especially useful for framework and third-party library code that wishes to register its own components to the container. It allows an application developer to override the framework or library’s default registration, even if the application developer registered that component before the framework or third-party AddXXX
extension method is called. For instance:
services.TryAddSingleton<IX, A>(); // adds A
services.AddThirdPartyLibrary (); // calls services.TryAddSingleton <IX, B>();
IX x = container.GetService<IX>(); // resolves A
如果第三方库调用了AddSingleton
而不是TryAddSingleton
,则应用程序开发人员的A
将始终被覆盖,这可能会使开发人员感到困惑.作为应用程序开发人员,您通常会知道自己注册了什么,这使得TryAddSingleton
的使用对应用程序开发人员没有太大用处.
Would the third-party library have called AddSingleton
instead of TryAddSingleton
, the application developer’s A
will always be overridden, which can be confusing for the developer.As an application developer, you typically know what you registered, which makes the use of TryAddSingleton
not that useful for an application developer.
我什至会争辩说,从应用程序开发人员的角度来看,AddSingleton
的行为可能非常棘手,因为它隐式地覆盖了现有注册,而没有任何警告.我的经验是,此行为可能导致难以发现配置错误.更安全的设计应该是具有AddSingleton
,AppendSingleton
和ReplaceSingleton
方法,其中AddSingleton
将在存在注册的情况下引发异常,而ReplaceSingleton
实际上将丢弃现有的注册.
I would even argue that, from perspective of an application developer, the behavior of AddSingleton
can be very tricky, because it implicitly overrides an existing registration, without any warning whatsoever. My experience is that this behavior can cause hard to spot configuration errors. A safer design would have been to have AddSingleton
, AppendSingleton
and ReplaceSingleton
methods, where AddSingleton
would throw an exception in case a registration exists, and ReplaceSingleton
would actually throw away the existing registration.
这篇关于什么时候使用TryAddSingleton或AddSingleton?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!