IServiceProvider.GetServices<T>() 是不是总是按注册顺序返回可用的服务实现?
Posted
技术标签:
【中文标题】IServiceProvider.GetServices<T>() 是不是总是按注册顺序返回可用的服务实现?【英文标题】:Does IServiceProvider.GetServices<T>() always returns the available service implementations in the registration order?IServiceProvider.GetServices<T>() 是否总是按注册顺序返回可用的服务实现? 【发布时间】:2021-08-28 15:11:43 【问题描述】:这个问题专门针对 ASP.NET core 3.1 和内置的依赖注入容器(Microsoft DI)。
Microsoft documentation 和 this *** question 确认,当为同一服务类型注册了多个实现类型时,Microsoft DI 容器始终通过遵守注册顺序来解析 IEnumerable<TService>
。订单有保证,并且有明确的记录。
有谁知道IServiceProvider.GetServices<T>()
方法是否同样适用?
如果上述问题的答案是肯定的,即使在以下示例中(同一类的两个不同实例注册为同一服务类型的实现),这是否也成立?
public interface IService
public sealed class Foo : IService
var foo1 = new Foo();
var foo2 = new Foo();
services.AddSingleton<IService>(foo1);
services.AddSingleton<IService>(foo2);
var implementations = serviceProvider.GetServices<IFoo>();
// is it guaranteed that implementations[0] == foo1 and implementations[1] == foo2 ???
【问题讨论】:
我不知道答案,但当您无法完全控制订单或提供集合的方法未明确保证时,我总是建议不要依赖集合中项目的顺序特定的顺序(例如将排序函数指定为方法的输入时)。否则,您将依赖可能随时更改的实现细节。 简短的回答是肯定的,因为在内部GetServices<T>
扩展方法解析 IEnumerable<T>
与将 IEnumerable<T>
作为注入依赖项的构造函数相同
【参考方案1】:
简短的回答是肯定的,因为内部 GetServices*
扩展方法解析 IEnumerable<T>
与将 IEnumerable<T>
作为注入依赖项的构造函数中相同
/// <summary>
/// Get an enumeration of services of type <typeparamref name="T"/> from the <see cref="IServiceProvider"/>.
/// </summary>
/// <typeparam name="T">The type of service object to get.</typeparam>
/// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the services from.</param>
/// <returns>An enumeration of services of type <typeparamref name="T"/>.</returns>
public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)
if (provider == null)
throw new ArgumentNullException(nameof(provider));
return provider.GetRequiredService<IEnumerable<T>>();
/// <summary>
/// Get an enumeration of services of type <paramref name="serviceType"/> from the <see cref="IServiceProvider"/>.
/// </summary>
/// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the services from.</param>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>An enumeration of services of type <paramref name="serviceType"/>.</returns>
public static IEnumerable<object?> GetServices(this IServiceProvider provider, Type serviceType)
if (provider == null)
throw new ArgumentNullException(nameof(provider));
if (serviceType == null)
throw new ArgumentNullException(nameof(serviceType));
Type? genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType);
return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable);
Source code
【讨论】:
以上是关于IServiceProvider.GetServices<T>() 是不是总是按注册顺序返回可用的服务实现?的主要内容,如果未能解决你的问题,请参考以下文章