From 02b1c4da66c4ecd94fb6db582e4832c9ffbecc46 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 6 Jun 2023 14:58:09 +0200 Subject: [PATCH 01/43] Keyed services --- .../src/CompatibilitySuppressions.xml | 100 ++ ...nsions.DependencyInjection.Abstractions.cs | 118 +- .../src/CompatibilitySuppressions.xml | 1426 +++++++++++++++++ .../ServiceCollectionDescriptorExtensions.cs | 2 +- .../src/FromKeyedServicesAttribute.cs | 15 + .../src/ISupportKeyedService.cs | 23 + .../src/ISupportRequiredKeyedService.cs | 24 + ...ServiceCollectionKeyedServiceExtensions.cs | 561 +++++++ .../src/ServiceDescriptor.cs | 457 +++++- .../src/ServiceKeyAttribute.cs | 12 + .../ServiceProviderKeyedServiceExtensions.cs | 111 ++ .../src/CompatibilitySuppressions.xml | 10 + ...icrosoft.Extensions.DependencyInjection.cs | 3 +- .../src/ServiceLookup/CallSiteChain.cs | 40 +- .../src/ServiceLookup/CallSiteFactory.cs | 180 ++- .../src/ServiceLookup/FactoryCallSite.cs | 7 + .../ILEmit/ILEmitResolverBuilder.cs | 8 +- .../src/ServiceLookup/ResultCache.cs | 8 +- .../src/ServiceLookup/ServiceCacheKey.cs | 16 +- .../ServiceDescriptorCacheKey.cs | 65 + .../ServiceProviderEngineScope.cs | 2 +- .../src/ServiceProvider.cs | 38 +- .../KeyedServiceProviderContainerTests.cs | 233 +++ .../ServiceLookup/CallSiteFactoryTest.cs | 11 +- .../ServiceProviderEngineScopeTests.cs | 2 +- .../src/CompatibilitySuppressions.xml | 1 + 26 files changed, 3334 insertions(+), 139 deletions(-) create mode 100644 src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/FromKeyedServicesAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceKeyAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs diff --git a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml new file mode 100644 index 0000000000000..80a467cc1f51f --- /dev/null +++ b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml @@ -0,0 +1,100 @@ + + + + + CP0001 + T:System.Collections.Generic.IAsyncEnumerable`1 + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Collections.Generic.IAsyncEnumerator`1 + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.IAsyncDisposable + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.AsyncIteratorMethodBuilder + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.ConfiguredAsyncDisposable + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Threading.Tasks.TaskAsyncEnumerableExtensions + ref/net462/Microsoft.Bcl.AsyncInterfaces.dll + lib/net462/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Collections.Generic.IAsyncEnumerable`1 + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Collections.Generic.IAsyncEnumerator`1 + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.IAsyncDisposable + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.AsyncIteratorMethodBuilder + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.ConfiguredAsyncDisposable + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + + CP0001 + T:System.Threading.Tasks.TaskAsyncEnumerableExtensions + ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index abb9b58cdbde2..f25e810c78fd8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -9,11 +9,11 @@ namespace Microsoft.Extensions.DependencyInjection public static partial class ActivatorUtilities { public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type instanceType, System.Type[] argumentTypes) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.Type[] argumentTypes) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory(System.Type[] argumentTypes) { throw null; } public static object CreateInstance(System.IServiceProvider provider, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type instanceType, params object[] parameters) { throw null; } - public static T CreateInstance<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.IServiceProvider provider, params object[] parameters) { throw null; } + public static T CreateInstance(System.IServiceProvider provider, params object[] parameters) { throw null; } public static object GetServiceOrCreateInstance(System.IServiceProvider provider, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type) { throw null; } - public static T GetServiceOrCreateInstance<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.IServiceProvider provider) { throw null; } + public static T GetServiceOrCreateInstance(System.IServiceProvider provider) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.All)] public partial class ActivatorUtilitiesConstructorAttribute : System.Attribute @@ -29,6 +29,12 @@ public ActivatorUtilitiesConstructorAttribute() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } } + [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] + public partial class FromKeyedServicesAttribute : System.Attribute + { + public FromKeyedServicesAttribute(object key) { } + public object Key { get { throw null; } } + } public partial interface IServiceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { } @@ -49,10 +55,22 @@ public partial interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } + public partial interface ISupportKeyedService + { + object? GetKeyedService(System.Type serviceType, object serviceKey); + } + public partial interface ISupportRequiredKeyedService + { + object GetRequiredKeyedService(System.Type serviceType, object serviceKey); + } public partial interface ISupportRequiredService { object GetRequiredService(System.Type serviceType); } + public static partial class KeyedService + { + public static object AnyKey { get { throw null; } } + } public delegate object ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public delegate T ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public partial class ServiceCollection : Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable @@ -73,70 +91,134 @@ public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.Add(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } + public static partial class ServiceCollectionKeyedServiceExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + } public static partial class ServiceCollectionServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object implementationInstance) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } } public partial class ServiceDescriptor { public ServiceDescriptor(System.Type serviceType, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object instance) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, object instance) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public System.Func? ImplementationFactory { get { throw null; } } public object? ImplementationInstance { get { throw null; } } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? ImplementationType { get { throw null; } } + public System.Func? KeyedImplementationFactory { get { throw null; } } public Microsoft.Extensions.DependencyInjection.ServiceLifetime Lifetime { get { throw null; } } + public object? ServiceKey { get { throw null; } } public System.Type ServiceType { get { throw null; } } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object serviceKey, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type serviceType, object implementationInstance) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } public override string ToString() { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } } + [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] + public partial class ServiceKeyAttribute : System.Attribute + { + public ServiceKeyAttribute() { } + } public enum ServiceLifetime { Singleton = 0, Scoped = 1, Transient = 2, } + public static partial class ServiceProviderKeyedServiceExtensions + { + [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("The native code for an IEnumerable might not be available at runtime.")] + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, object serviceKey) { throw null; } + public static T? GetKeyedService(this System.IServiceProvider provider, object serviceKey) { throw null; } + public static object GetRequiredKeyedService(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } + public static T GetRequiredKeyedService(this System.IServiceProvider provider, object serviceKey) where T : notnull { throw null; } + } public static partial class ServiceProviderServiceExtensions { public static Microsoft.Extensions.DependencyInjection.AsyncServiceScope CreateAsyncScope(this Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) { throw null; } @@ -166,21 +248,21 @@ public static void TryAddEnumerable(this Microsoft.Extensions.DependencyInjectio public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } - public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, TService instance) where TService : class { } - public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } - public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml new file mode 100644 index 0000000000000..f3d1040ea4b55 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -0,0 +1,1426 @@ + + + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0016 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs index 4f99cd94cb85f..0ec8690594060 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs @@ -411,7 +411,7 @@ public static void TryAddSingleton(this IServiceCollection collection, ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(instance); - var descriptor = ServiceDescriptor.Singleton(typeof(TService), instance); + var descriptor = ServiceDescriptor.Singleton(serviceType: typeof(TService), implementationInstance: instance); TryAdd(collection, descriptor); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/FromKeyedServicesAttribute.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/FromKeyedServicesAttribute.cs new file mode 100644 index 0000000000000..a7ff22e94b59e --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/FromKeyedServicesAttribute.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + [AttributeUsage(AttributeTargets.Parameter)] + public class FromKeyedServicesAttribute : Attribute + { + public FromKeyedServicesAttribute(object key) => Key = key; + + public object Key { get; } + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs new file mode 100644 index 0000000000000..25ed579f07fe5 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + public interface ISupportKeyedService + { + /// + /// Gets the service object of the specified type. + /// + /// An object that specifies the type of service object to get. + /// An object that specifies the key of service object to get. + /// A service object of type serviceType. -or- null if there is no service object of type serviceType. + object? GetKeyedService(Type serviceType, object serviceKey); + } + + public static class KeyedService + { + public static object AnyKey { get; } = new object(); + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs new file mode 100644 index 0000000000000..c4d398ee1c08f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Optional contract used by + /// to resolve services if supported by . + /// + public interface ISupportRequiredKeyedService + { + /// + /// Gets service of type from the implementing + /// this interface. + /// + /// An object that specifies the type of service object to get. + /// The of the service. + /// A service object of type . + /// Throws an exception if the cannot create the object. + object GetRequiredKeyedService(Type serviceType, object serviceKey); + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs new file mode 100644 index 0000000000000..8eddf3c4513f6 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs @@ -0,0 +1,561 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extension methods for adding services to an . + /// + public static class ServiceCollectionKeyedServiceExtensions + { + /// + /// Adds a transient service of the type specified in with an + /// implementation of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The implementation type of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + Type serviceType, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationType); + + return AddKeyed(services, serviceType, serviceKey, implementationType, ServiceLifetime.Transient); + } + + /// + /// Adds a transient service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + Type serviceType, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationFactory); + + return AddKeyed(services, serviceType, serviceKey, implementationFactory, ServiceLifetime.Transient); + } + + /// + /// Adds a transient service of the type specified in with an + /// implementation type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedTransient(typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds a transient service of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register and the implementation to use. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, + object serviceKey) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + + return services.AddKeyedTransient(serviceType, serviceKey, serviceType); + } + + /// + /// Adds a transient service of the type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( + this IServiceCollection services, + object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedTransient(typeof(TService), serviceKey); + } + + /// + /// Adds a transient service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedTransient(typeof(TService), serviceKey, implementationFactory); + } + + /// + /// Adds a transient service of the type specified in with an + /// implementation type specified in using the + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedTransient( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedTransient(typeof(TService), serviceKey, implementationFactory); + } + + /// + /// Adds a scoped service of the type specified in with an + /// implementation of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The implementation type of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + Type serviceType, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationType); + + return AddKeyed(services, serviceType, serviceKey, implementationType, ServiceLifetime.Scoped); + } + + /// + /// Adds a scoped service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + Type serviceType, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationFactory); + + return AddKeyed(services, serviceType, serviceKey, implementationFactory, ServiceLifetime.Scoped); + } + + /// + /// Adds a scoped service of the type specified in with an + /// implementation type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedScoped(typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds a scoped service of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register and the implementation to use. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, + object serviceKey) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + + return services.AddKeyedScoped(serviceType, serviceKey, serviceType); + } + + /// + /// Adds a scoped service of the type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( + this IServiceCollection services, + object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedScoped(typeof(TService), serviceKey); + } + + /// + /// Adds a scoped service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedScoped(typeof(TService), serviceKey, implementationFactory); + } + + /// + /// Adds a scoped service of the type specified in with an + /// implementation type specified in using the + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedScoped( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedScoped(typeof(TService), serviceKey, implementationFactory); + } + + + /// + /// Adds a singleton service of the type specified in with an + /// implementation of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The implementation type of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + Type serviceType, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationType); + + return AddKeyed(services, serviceType, serviceKey, implementationType, ServiceLifetime.Singleton); + } + + /// + /// Adds a singleton service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + Type serviceType, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationFactory); + + return AddKeyed(services, serviceType, serviceKey, implementationFactory, ServiceLifetime.Singleton); + } + + /// + /// Adds a singleton service of the type specified in with an + /// implementation type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedSingleton(typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds a singleton service of the type specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register and the implementation to use. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, + object serviceKey) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + + return services.AddKeyedSingleton(serviceType, serviceKey, serviceType); + } + + /// + /// Adds a singleton service of the type specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( + this IServiceCollection services, + object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + + return services.AddKeyedSingleton(typeof(TService), serviceKey, typeof(TService)); + } + + /// + /// Adds a singleton service of the type specified in with a + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedSingleton(typeof(TService), serviceKey, implementationFactory); + } + + /// + /// Adds a singleton service of the type specified in with an + /// implementation type specified in using the + /// factory specified in to the + /// specified . + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The to add the service to. + /// The of the service. + /// The factory that creates the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationFactory); + + return services.AddKeyedSingleton(typeof(TService), serviceKey, implementationFactory); + } + + /// + /// Adds a singleton service of the type specified in with an + /// instance specified in to the + /// specified . + /// + /// The to add the service to. + /// The type of the service to register. + /// The of the service. + /// The instance of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + Type serviceType, + object serviceKey, + object implementationInstance) + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationInstance); + + var serviceDescriptor = new ServiceDescriptor(serviceType, serviceKey, implementationInstance); + services.Add(serviceDescriptor); + return services; + } + + /// + /// Adds a singleton service of the type specified in with an + /// instance specified in to the + /// specified . + /// + /// The to add the service to. + /// The of the service. + /// The instance of the service. + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddKeyedSingleton( + this IServiceCollection services, + object serviceKey, + TService implementationInstance) + where TService : class + { + ThrowHelper.ThrowIfNull(services); + ThrowHelper.ThrowIfNull(implementationInstance); + + return services.AddKeyedSingleton(typeof(TService), serviceKey, implementationInstance); + } + + private static IServiceCollection AddKeyed( + IServiceCollection collection, + Type serviceType, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, + ServiceLifetime lifetime) + { + var descriptor = new ServiceDescriptor(serviceType, serviceKey, implementationType, lifetime); + collection.Add(descriptor); + return collection; + } + + private static IServiceCollection AddKeyed( + IServiceCollection collection, + Type serviceType, + object serviceKey, + Func implementationFactory, + ServiceLifetime lifetime) + { + var descriptor = new ServiceDescriptor(serviceType, serviceKey, implementationFactory, lifetime); + collection.Add(descriptor); + return collection; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index 5489892479d1b..178b04a53975b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -23,7 +23,23 @@ public ServiceDescriptor( Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) - : this(serviceType, lifetime) + : this(serviceType, null, implementationType, lifetime) + { + } + + /// + /// Initializes a new instance of with the specified . + /// + /// The of the service. + /// The of the service. + /// The implementing the service. + /// The of the service. + public ServiceDescriptor( + Type serviceType, + object? serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, + ServiceLifetime lifetime) + : this(serviceType, serviceKey, lifetime) { ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(implementationType); @@ -40,7 +56,22 @@ public ServiceDescriptor( public ServiceDescriptor( Type serviceType, object instance) - : this(serviceType, ServiceLifetime.Singleton) + : this(serviceType, null, instance) + { + } + + /// + /// Initializes a new instance of with the specified + /// as a . + /// + /// The of the service. + /// The of the service. + /// The instance implementing the service. + public ServiceDescriptor( + Type serviceType, + object? serviceKey, + object instance) + : this(serviceType, serviceKey, ServiceLifetime.Singleton) { ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(instance); @@ -58,7 +89,7 @@ public ServiceDescriptor( Type serviceType, Func factory, ServiceLifetime lifetime) - : this(serviceType, lifetime) + : this(serviceType, serviceKey: null, lifetime) { ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(factory); @@ -66,10 +97,31 @@ public ServiceDescriptor( ImplementationFactory = factory; } - private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) + /// + /// Initializes a new instance of with the specified . + /// + /// The of the service. + /// The of the service. + /// A factory used for creating service instances. + /// The of the service. + public ServiceDescriptor( + Type serviceType, + object? serviceKey, + Func factory, + ServiceLifetime lifetime) + : this(serviceType, serviceKey, lifetime) + { + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(factory); + + KeyedImplementationFactory = factory; + } + + private ServiceDescriptor(Type serviceType, object? serviceKey, ServiceLifetime lifetime) { Lifetime = lifetime; ServiceType = serviceType; + ServiceKey = serviceKey; } /// @@ -77,6 +129,11 @@ private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) /// public ServiceLifetime Lifetime { get; } + /// + /// Get the key of the service, if applicable. + /// + public object? ServiceKey { get; } + /// /// Gets the of the service. /// @@ -98,11 +155,21 @@ private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) /// public Func? ImplementationFactory { get; } + /// + /// Gets the factory used for creating Keyed service instances. + /// + public Func? KeyedImplementationFactory { get; } + /// public override string ToString() { string? lifetime = $"{nameof(ServiceType)}: {ServiceType} {nameof(Lifetime)}: {Lifetime} "; + if (ServiceKey != null) + { + lifetime += $"{nameof(ServiceKey)}: {ServiceKey} "; + } + if (ImplementationType != null) { return lifetime + $"{nameof(ImplementationType)}: {ImplementationType}"; @@ -113,6 +180,11 @@ public override string ToString() return lifetime + $"{nameof(ImplementationFactory)}: {ImplementationFactory.Method}"; } + if (KeyedImplementationFactory != null) + { + return lifetime + $"{nameof(KeyedImplementationFactory)}: {KeyedImplementationFactory.Method}"; + } + return lifetime + $"{nameof(ImplementationInstance)}: {ImplementationInstance}"; } @@ -134,8 +206,16 @@ internal Type GetImplementationType() return typeArguments[1]; } + else if (KeyedImplementationFactory != null) + { + Type[]? typeArguments = KeyedImplementationFactory.GetType().GenericTypeArguments; - Debug.Assert(false, "ImplementationType, ImplementationInstance or ImplementationFactory must be non null"); + Debug.Assert(typeArguments.Length == 3); + + return typeArguments[2]; + } + + Debug.Assert(false, "ImplementationType, ImplementationInstance, ImplementationFactory or KeyedImplementationFactory must be non null"); return null; } @@ -151,7 +231,23 @@ internal Type GetImplementationType() where TService : class where TImplementation : class, TService { - return Describe(ServiceLifetime.Transient); + return DescribeKeyed(null, ServiceLifetime.Transient); + } + + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A new instance of . + public static ServiceDescriptor KeyedTransient(object serviceKey) + where TService : class + where TImplementation : class, TService + { + return DescribeKeyed(serviceKey, ServiceLifetime.Transient); } /// @@ -172,6 +268,26 @@ public static ServiceDescriptor Transient( return Describe(service, implementationType, ServiceLifetime.Transient); } + /// + /// Creates an instance of with the specified + /// and + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// The type of the implementation. + /// A new instance of . + public static ServiceDescriptor KeyedTransient( + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationType); + + return DescribeKeyed(service, serviceKey, implementationType, ServiceLifetime.Transient); + } + /// /// Creates an instance of with the specified /// , , @@ -192,6 +308,28 @@ public static ServiceDescriptor Transient( return Describe(typeof(TService), implementationFactory, ServiceLifetime.Transient); } + /// + /// Creates an instance of with the specified + /// , , + /// , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedTransient( + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Transient); + } + /// /// Creates an instance of with the specified /// , , @@ -208,6 +346,23 @@ public static ServiceDescriptor Transient(Func + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedTransient(object serviceKey, Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Transient); + } + /// /// Creates an instance of with the specified /// , , @@ -224,6 +379,23 @@ public static ServiceDescriptor Transient(Type service, Func + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedTransient(Type service, object serviceKey, Func implementationFactory) + { + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(service, serviceKey, implementationFactory, ServiceLifetime.Transient); + } + /// /// Creates an instance of with the specified /// , , @@ -236,7 +408,23 @@ public static ServiceDescriptor Transient(Type service, Func(ServiceLifetime.Scoped); + return DescribeKeyed(null, ServiceLifetime.Scoped); + } + + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A new instance of . + public static ServiceDescriptor KeyedScoped(object serviceKey) + where TService : class + where TImplementation : class, TService + { + return DescribeKeyed(serviceKey, ServiceLifetime.Scoped); } /// @@ -254,6 +442,23 @@ public static ServiceDescriptor Scoped( return Describe(service, implementationType, ServiceLifetime.Scoped); } + /// + /// Creates an instance of with the specified + /// and + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// The type of the implementation. + /// A new instance of . + public static ServiceDescriptor KeyedScoped( + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + return DescribeKeyed(service, serviceKey, implementationType, ServiceLifetime.Scoped); + } + /// /// Creates an instance of with the specified /// , , @@ -274,6 +479,28 @@ public static ServiceDescriptor Scoped( return Describe(typeof(TService), implementationFactory, ServiceLifetime.Scoped); } + /// + /// Creates an instance of with the specified + /// , , + /// , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedScoped( + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Scoped); + } + /// /// Creates an instance of with the specified /// , , @@ -290,6 +517,23 @@ public static ServiceDescriptor Scoped(Func + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedScoped(object serviceKey, Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Scoped); + } + /// /// Creates an instance of with the specified /// , , @@ -306,6 +550,23 @@ public static ServiceDescriptor Scoped(Type service, Func + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedScoped(Type service, object serviceKey, Func implementationFactory) + { + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(service, serviceKey, implementationFactory, ServiceLifetime.Scoped); + } + /// /// Creates an instance of with the specified /// , , @@ -318,7 +579,24 @@ public static ServiceDescriptor Scoped(Type service, Func(ServiceLifetime.Singleton); + return DescribeKeyed(null, ServiceLifetime.Singleton); + } + + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A new instance of . + public static ServiceDescriptor Singleton( + object serviceKey) + where TService : class + where TImplementation : class, TService + { + return DescribeKeyed(serviceKey, ServiceLifetime.Singleton); } /// @@ -339,6 +617,26 @@ public static ServiceDescriptor Singleton( return Describe(service, implementationType, ServiceLifetime.Singleton); } + /// + /// Creates an instance of with the specified + /// and + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// The type of the implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationType); + + return DescribeKeyed(service, serviceKey, implementationType, ServiceLifetime.Singleton); + } + /// /// Creates an instance of with the specified /// , , @@ -359,6 +657,28 @@ public static ServiceDescriptor Singleton( return Describe(typeof(TService), implementationFactory, ServiceLifetime.Singleton); } + /// + /// Creates an instance of with the specified + /// , , + /// , + /// and the lifetime. + /// + /// The type of the service. + /// The type of the implementation. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + object serviceKey, + Func implementationFactory) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Singleton); + } + /// /// Creates an instance of with the specified /// , , @@ -375,6 +695,25 @@ public static ServiceDescriptor Singleton(Func + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + object serviceKey, + Func implementationFactory) + where TService : class + { + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(typeof(TService), serviceKey, implementationFactory, ServiceLifetime.Singleton); + } + /// /// Creates an instance of with the specified /// , , @@ -393,6 +732,26 @@ public static ServiceDescriptor Singleton( return Describe(serviceType, implementationFactory, ServiceLifetime.Singleton); } + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + Type serviceType, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationFactory); + + return DescribeKeyed(serviceType, serviceKey, implementationFactory, ServiceLifetime.Singleton); + } + /// /// Creates an instance of with the specified /// , , @@ -406,7 +765,26 @@ public static ServiceDescriptor Singleton(TService implementationInsta { ThrowHelper.ThrowIfNull(implementationInstance); - return Singleton(typeof(TService), implementationInstance); + return Singleton(serviceType: typeof(TService), implementationInstance: implementationInstance); + } + + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// The instance of the implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + object serviceKey, + TService implementationInstance) + where TService : class + { + ThrowHelper.ThrowIfNull(implementationInstance); + + return KeyedSingleton(typeof(TService), serviceKey, implementationInstance); } /// @@ -427,12 +805,35 @@ public static ServiceDescriptor Singleton( return new ServiceDescriptor(serviceType, implementationInstance); } - private static ServiceDescriptor Describe(ServiceLifetime lifetime) + /// + /// Creates an instance of with the specified + /// , , + /// and the lifetime. + /// + /// The type of the service. + /// The of the service. + /// The instance of the implementation. + /// A new instance of . + public static ServiceDescriptor KeyedSingleton( + Type serviceType, + object serviceKey, + object implementationInstance) + { + ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(implementationInstance); + + return new ServiceDescriptor(serviceType, serviceKey, implementationInstance); + } + + private static ServiceDescriptor DescribeKeyed( + object? serviceKey, + ServiceLifetime lifetime) where TService : class where TImplementation : class, TService { - return Describe( + return DescribeKeyed( typeof(TService), + serviceKey, typeof(TImplementation), lifetime: lifetime); } @@ -454,6 +855,25 @@ public static ServiceDescriptor Describe( return new ServiceDescriptor(serviceType, implementationType, lifetime); } + /// + /// Creates an instance of with the specified + /// , , + /// and . + /// + /// The type of the service. + /// The of the service. + /// The type of the implementation. + /// The lifetime of the service. + /// A new instance of . + public static ServiceDescriptor DescribeKeyed( + Type serviceType, + object? serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, + ServiceLifetime lifetime) + { + return new ServiceDescriptor(serviceType, serviceKey, implementationType, lifetime); + } + /// /// Creates an instance of with the specified /// , , @@ -468,6 +888,21 @@ public static ServiceDescriptor Describe(Type serviceType, Func + /// Creates an instance of with the specified + /// , , + /// and . + /// + /// The type of the service. + /// The of the service. + /// A factory to create new instances of the service implementation. + /// The lifetime of the service. + /// A new instance of . + public static ServiceDescriptor DescribeKeyed(Type serviceType, object serviceKey, Func implementationFactory, ServiceLifetime lifetime) + { + return new ServiceDescriptor(serviceType, serviceKey, implementationFactory, lifetime); + } + private string DebuggerToString() { string debugText = $@"Lifetime = {Lifetime}, ServiceType = ""{ServiceType.FullName}"""; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceKeyAttribute.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceKeyAttribute.cs new file mode 100644 index 0000000000000..f9dfc985b82e6 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceKeyAttribute.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + [AttributeUsage(AttributeTargets.Parameter)] + public class ServiceKeyAttribute : Attribute + { + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs new file mode 100644 index 0000000000000..2da454c61e01d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extension methods for getting services from an . + /// + public static class ServiceProviderKeyedServiceExtensions + { + /// + /// Get service of type from the . + /// + /// The type of service object to get. + /// The to retrieve the service object from. + /// An object that specifies the key of service object to get. + /// A service object of type or null if there is no such service. + public static T? GetKeyedService(this IServiceProvider provider, object serviceKey) + { + ThrowHelper.ThrowIfNull(provider); + + if (provider is ISupportKeyedService keyedServiceProvider) + { + return (T?)keyedServiceProvider.GetKeyedService(typeof(T), serviceKey); + } + + throw new InvalidOperationException("TODO BPETIT"); + } + + /// + /// Get service of type from the . + /// + /// The to retrieve the service object from. + /// An object that specifies the type of service object to get. + /// An object that specifies the key of service object to get. + /// A service object of type . + /// There is no service of type . + public static object GetRequiredKeyedService(this IServiceProvider provider, Type serviceType, object serviceKey) + { + ThrowHelper.ThrowIfNull(provider); + ThrowHelper.ThrowIfNull(serviceType); + + if (provider is ISupportRequiredKeyedService requiredServiceSupportingProvider) + { + return requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey); + } + + if (provider is ISupportKeyedService keyedServiceProvider) + { + object? service = keyedServiceProvider.GetKeyedService(serviceType, serviceKey); + if (service == null) + { + throw new InvalidOperationException(SR.Format(SR.NoServiceRegistered, serviceType)); + } + return service; + } + + throw new InvalidOperationException("TODO BPETIT"); + } + + /// + /// Get service of type from the . + /// + /// The type of service object to get. + /// The to retrieve the service object from. + /// An object that specifies the key of service object to get. + /// A service object of type . + /// There is no service of type . + public static T GetRequiredKeyedService(this IServiceProvider provider, object serviceKey) where T : notnull + { + ThrowHelper.ThrowIfNull(provider); + + return (T)provider.GetRequiredKeyedService(typeof(T), serviceKey); + } + + /// + /// Get an enumeration of services of type from the . + /// + /// The type of service object to get. + /// The to retrieve the services from. + /// An object that specifies the key of service object to get. + /// An enumeration of services of type . + public static IEnumerable GetKeyedServices(this IServiceProvider provider, object serviceKey) + { + ThrowHelper.ThrowIfNull(provider); + + return provider.GetRequiredKeyedService>(serviceKey); + } + + /// + /// Get an enumeration of services of type from the . + /// + /// The to retrieve the services from. + /// An object that specifies the type of service object to get. + /// An object that specifies the key of service object to get. + /// An enumeration of services of type . + [RequiresDynamicCode("The native code for an IEnumerable might not be available at runtime.")] + public static IEnumerable GetKeyedServices(this IServiceProvider provider, Type serviceType, object serviceKey) + { + ThrowHelper.ThrowIfNull(provider); + ThrowHelper.ThrowIfNull(serviceType); + + Type? genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType); + return (IEnumerable)provider.GetRequiredKeyedService(genericEnumerable, serviceKey); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml index c4c68039b773f..0357fdc8d5e24 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml @@ -2,6 +2,16 @@ + + CP0002 + M:Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.#ctor(System.DateTime,System.DateTime,System.TimeSpan,System.TimeSpan,System.DateTimeOffset,System.DateTimeOffset,System.Guid,System.Guid,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,System.Nullable{System.ConsoleColor},System.Nullable{System.ConsoleColor},System.Nullable{System.Int32},System.Nullable{System.Int32}) + true + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.ExplictServiceRegisterationWithIsService + true + CP0002 M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.TypeActivatorCreateInstanceUsesFirstMathchedConstructor(System.Object,System.String) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index 0b85156d60885..76fa03d55a66b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -19,11 +19,12 @@ public static partial class ServiceCollectionContainerBuilderExtensions public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.DependencyInjection.ServiceProviderOptions options) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, bool validateScopes) { throw null; } } - public sealed partial class ServiceProvider : System.IAsyncDisposable, System.IDisposable, System.IServiceProvider + public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInjection.ISupportKeyedService, System.IAsyncDisposable, System.IDisposable, System.IServiceProvider { internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public object GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs index 3163b22a778fa..6fcba896d7723 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs @@ -10,58 +10,58 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { internal sealed class CallSiteChain { - private readonly Dictionary _callSiteChain; + private readonly Dictionary _callSiteChain; public CallSiteChain() { - _callSiteChain = new Dictionary(); + _callSiteChain = new Dictionary(); } - public void CheckCircularDependency(Type serviceType) + public void CheckCircularDependency(ServiceIdentifier serviceIdentifier) { - if (_callSiteChain.ContainsKey(serviceType)) + if (_callSiteChain.ContainsKey(serviceIdentifier)) { - throw new InvalidOperationException(CreateCircularDependencyExceptionMessage(serviceType)); + throw new InvalidOperationException(CreateCircularDependencyExceptionMessage(serviceIdentifier)); } } - public void Remove(Type serviceType) + public void Remove(ServiceIdentifier serviceIdentifier) { - _callSiteChain.Remove(serviceType); + _callSiteChain.Remove(serviceIdentifier); } - public void Add(Type serviceType, Type? implementationType = null) + public void Add(ServiceIdentifier serviceIdentifier, Type? implementationType = null) { - _callSiteChain[serviceType] = new ChainItemInfo(_callSiteChain.Count, implementationType); + _callSiteChain[serviceIdentifier] = new ChainItemInfo(_callSiteChain.Count, implementationType); } - private string CreateCircularDependencyExceptionMessage(Type type) + private string CreateCircularDependencyExceptionMessage(ServiceIdentifier serviceIdentifier) { var messageBuilder = new StringBuilder(); - messageBuilder.Append(SR.Format(SR.CircularDependencyException, TypeNameHelper.GetTypeDisplayName(type))); + messageBuilder.Append(SR.Format(SR.CircularDependencyException, TypeNameHelper.GetTypeDisplayName(serviceIdentifier.ServiceType))); messageBuilder.AppendLine(); - AppendResolutionPath(messageBuilder, type); + AppendResolutionPath(messageBuilder, serviceIdentifier); return messageBuilder.ToString(); } - private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving) + private void AppendResolutionPath(StringBuilder builder, ServiceIdentifier currentlyResolving) { - var ordered = new List>(_callSiteChain); + var ordered = new List>(_callSiteChain); ordered.Sort((a, b) => a.Value.Order.CompareTo(b.Value.Order)); - foreach (KeyValuePair pair in ordered) + foreach (KeyValuePair pair in ordered) { - Type serviceType = pair.Key; + ServiceIdentifier serviceIdentifier = pair.Key; Type? implementationType = pair.Value.ImplementationType; - if (implementationType == null || serviceType == implementationType) + if (implementationType == null || serviceIdentifier.ServiceType == implementationType) { - builder.Append(TypeNameHelper.GetTypeDisplayName(serviceType)); + builder.Append(TypeNameHelper.GetTypeDisplayName(serviceIdentifier.ServiceType)); } else { - builder.Append(TypeNameHelper.GetTypeDisplayName(serviceType)) + builder.Append(TypeNameHelper.GetTypeDisplayName(serviceIdentifier.ServiceType)) .Append('(') .Append(TypeNameHelper.GetTypeDisplayName(implementationType)) .Append(')'); @@ -70,7 +70,7 @@ private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving builder.Append(" -> "); } - builder.Append(TypeNameHelper.GetTypeDisplayName(currentlyResolving)); + builder.Append(TypeNameHelper.GetTypeDisplayName(currentlyResolving.ServiceType)); } private readonly struct ChainItemInfo diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 908d46787f13a..81c995f209447 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -16,8 +16,8 @@ internal sealed class CallSiteFactory : IServiceProviderIsService private const int DefaultSlot = 0; private readonly ServiceDescriptor[] _descriptors; private readonly ConcurrentDictionary _callSiteCache = new ConcurrentDictionary(); - private readonly Dictionary _descriptorLookup = new Dictionary(); - private readonly ConcurrentDictionary _callSiteLocks = new ConcurrentDictionary(); + private readonly Dictionary _descriptorLookup = new Dictionary(); + private readonly ConcurrentDictionary _callSiteLocks = new ConcurrentDictionary(); private readonly StackGuard _stackGuard; @@ -67,7 +67,7 @@ private void Populate() ValidateTrimmingAnnotations(serviceType, serviceTypeGenericArguments, implementationType, implementationTypeGenericArguments); } } - else if (descriptor.ImplementationInstance == null && descriptor.ImplementationFactory == null) + else if (descriptor.ImplementationInstance == null && descriptor.ImplementationFactory == null && descriptor.KeyedImplementationFactory == null) { Debug.Assert(descriptor.ImplementationType != null); Type implementationType = descriptor.ImplementationType; @@ -81,7 +81,7 @@ private void Populate() } } - Type cacheKey = serviceType; + var cacheKey = ServiceIdentifier.FromDescriptor(descriptor); _descriptorLookup.TryGetValue(cacheKey, out ServiceDescriptorCacheItem cacheItem); _descriptorLookup[cacheKey] = cacheItem.Add(descriptor); } @@ -152,7 +152,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica // For unit testing internal int? GetSlot(ServiceDescriptor serviceDescriptor) { - if (_descriptorLookup.TryGetValue(serviceDescriptor.ServiceType, out ServiceDescriptorCacheItem item)) + if (_descriptorLookup.TryGetValue(ServiceIdentifier.FromDescriptor(serviceDescriptor), out ServiceDescriptorCacheItem item)) { return item.GetSlot(serviceDescriptor); } @@ -160,26 +160,27 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica return null; } - internal ServiceCallSite? GetCallSite(Type serviceType, CallSiteChain callSiteChain) => - _callSiteCache.TryGetValue(new ServiceCacheKey(serviceType, DefaultSlot), out ServiceCallSite? site) ? site : - CreateCallSite(serviceType, callSiteChain); + internal ServiceCallSite? GetCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain) => + _callSiteCache.TryGetValue(new ServiceCacheKey(serviceIdentifier, DefaultSlot), out ServiceCallSite? site) ? site : + CreateCallSite(serviceIdentifier, callSiteChain); internal ServiceCallSite? GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) { - if (_descriptorLookup.TryGetValue(serviceDescriptor.ServiceType, out ServiceDescriptorCacheItem descriptor)) + var serviceIdentifier = ServiceIdentifier.FromDescriptor(serviceDescriptor); + if (_descriptorLookup.TryGetValue(serviceIdentifier, out ServiceDescriptorCacheItem descriptor)) { - return TryCreateExact(serviceDescriptor, serviceDescriptor.ServiceType, callSiteChain, descriptor.GetSlot(serviceDescriptor)); + return TryCreateExact(serviceDescriptor, serviceIdentifier, callSiteChain, descriptor.GetSlot(serviceDescriptor)); } Debug.Fail("_descriptorLookup didn't contain requested serviceDescriptor"); return null; } - private ServiceCallSite? CreateCallSite(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? CreateCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain) { if (!_stackGuard.TryEnterOnCurrentStack()) { - return _stackGuard.RunOnEmptyStack(CreateCallSite, serviceType, callSiteChain); + return _stackGuard.RunOnEmptyStack(CreateCallSite, serviceIdentifier, callSiteChain); } // We need to lock the resolution process for a single service type at a time: @@ -192,44 +193,67 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica // This is to make sure we can safely store singleton values on the callsites themselves - var callsiteLock = _callSiteLocks.GetOrAdd(serviceType, static _ => new object()); + var callsiteLock = _callSiteLocks.GetOrAdd(serviceIdentifier, static _ => new object()); lock (callsiteLock) { - callSiteChain.CheckCircularDependency(serviceType); + callSiteChain.CheckCircularDependency(serviceIdentifier); - ServiceCallSite? callSite = TryCreateExact(serviceType, callSiteChain) ?? - TryCreateOpenGeneric(serviceType, callSiteChain) ?? - TryCreateEnumerable(serviceType, callSiteChain); + ServiceCallSite? callSite = TryCreateExact(serviceIdentifier, callSiteChain) ?? + TryCreateOpenGeneric(serviceIdentifier, callSiteChain) ?? + TryCreateEnumerable(serviceIdentifier, callSiteChain); return callSite; } } - private ServiceCallSite? TryCreateExact(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateExact(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain) { - if (_descriptorLookup.TryGetValue(serviceType, out ServiceDescriptorCacheItem descriptor)) + if (_descriptorLookup.TryGetValue(serviceIdentifier, out ServiceDescriptorCacheItem descriptor)) { - return TryCreateExact(descriptor.Last, serviceType, callSiteChain, DefaultSlot); + return TryCreateExact(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot); + } + + if (serviceIdentifier.ServiceKey != null) + { + // Check if there is a registration with KeyedService.AnyKey + var catchAllIdentifier = new ServiceIdentifier(KeyedService.AnyKey, serviceIdentifier.ServiceType); + if (_descriptorLookup.TryGetValue(catchAllIdentifier, out descriptor)) + { + return TryCreateExact(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot); + } } return null; } - private ServiceCallSite? TryCreateOpenGeneric(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateOpenGeneric(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain) { - if (serviceType.IsConstructedGenericType - && _descriptorLookup.TryGetValue(serviceType.GetGenericTypeDefinition(), out ServiceDescriptorCacheItem descriptor)) + if (serviceIdentifier.IsConstructedGenericType) { - return TryCreateOpenGeneric(descriptor.Last, serviceType, callSiteChain, DefaultSlot, true); + var genericIdentifier = serviceIdentifier.GetGenericTypeDefinition(); + if (_descriptorLookup.TryGetValue(genericIdentifier, out ServiceDescriptorCacheItem descriptor)) + { + return TryCreateOpenGeneric(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot, true); + } + + if (serviceIdentifier.ServiceKey != null) + { + // Check if there is a registration with KeyedService.AnyKey + var catchAllIdentifier = new ServiceIdentifier(KeyedService.AnyKey, genericIdentifier.ServiceType); + if (_descriptorLookup.TryGetValue(catchAllIdentifier, out descriptor)) + { + return TryCreateOpenGeneric(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot, true); + } + } } return null; } - private ServiceCallSite? TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain) + private ServiceCallSite? TryCreateEnumerable(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain) { - ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, DefaultSlot); + ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceIdentifier, DefaultSlot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; @@ -237,7 +261,9 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica try { - callSiteChain.Add(serviceType); + callSiteChain.Add(serviceIdentifier); + + var serviceType = serviceIdentifier.ServiceType; if (!serviceType.IsConstructedGenericType || serviceType.GetGenericTypeDefinition() != typeof(IEnumerable<>)) @@ -246,6 +272,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica } Type itemType = serviceType.GenericTypeArguments[0]; + var cacheKey = ServiceIdentifier.FromServiceType(itemType); if (ServiceProvider.VerifyAotCompatibility && itemType.IsValueType) { // NativeAOT apps are not able to make Enumerable of ValueType services @@ -258,7 +285,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica // If item type is not generic we can safely use descriptor cache if (!itemType.IsConstructedGenericType && - _descriptorLookup.TryGetValue(itemType, out ServiceDescriptorCacheItem descriptors)) + _descriptorLookup.TryGetValue(cacheKey, out ServiceDescriptorCacheItem descriptors)) { callSites = new ServiceCallSite[descriptors.Count]; for (int i = 0; i < descriptors.Count; i++) @@ -268,7 +295,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica // Last service should get slot 0 int slot = descriptors.Count - i - 1; // There may not be any open generics here - ServiceCallSite? callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot); + ServiceCallSite? callSite = TryCreateExact(descriptor, cacheKey, callSiteChain, slot); Debug.Assert(callSite != null); cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); @@ -288,14 +315,14 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica int slot = 0; for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (TryCreateExact(_descriptors[i], itemType, callSiteChain, slot) is { } callSite) + if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite) { AddCallSite(callSite, i); } } for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (TryCreateOpenGeneric(_descriptors[i], itemType, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) + if (TryCreateOpenGeneric(_descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) { AddCallSite(callSite, i); } @@ -323,7 +350,7 @@ void AddCallSite(ServiceCallSite callSite, int index) } finally { - callSiteChain.Remove(serviceType); + callSiteChain.Remove(serviceIdentifier); } } @@ -332,18 +359,18 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult return (CallSiteResultCacheLocation)Math.Max((int)locationA, (int)locationB); } - private ServiceCallSite? TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) + private ServiceCallSite? TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, int slot) { - if (serviceType == descriptor.ServiceType) + if (serviceIdentifier.ServiceType == descriptor.ServiceType) { - ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); + ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceIdentifier, slot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; } ServiceCallSite callSite; - var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); + var lifetime = new ResultCache(descriptor.Lifetime, serviceIdentifier, slot); if (descriptor.ImplementationInstance != null) { callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance); @@ -352,9 +379,14 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult { callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } + else if (descriptor.KeyedImplementationFactory != null) + { + // TODO BPETIT FIXEME + callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, serviceIdentifier.ServiceKey!, descriptor.KeyedImplementationFactory); + } else if (descriptor.ImplementationType != null) { - callSite = CreateConstructorCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationType, callSiteChain); + callSite = CreateConstructorCallSite(lifetime, serviceIdentifier, descriptor.ImplementationType, callSiteChain); } else { @@ -374,26 +406,26 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", Justification = "When ServiceProvider.VerifyAotCompatibility is true, which it is by default when PublishAot=true, " + "this method ensures the generic types being created aren't using ValueTypes.")] - private ServiceCallSite? TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) + private ServiceCallSite? TryCreateOpenGeneric(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { - if (serviceType.IsConstructedGenericType && - serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) + if (serviceIdentifier.IsConstructedGenericType && + serviceIdentifier.ServiceType.GetGenericTypeDefinition() == descriptor.ServiceType) { - ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); + ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceIdentifier, slot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)) { return serviceCallSite; } Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); - var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); + var lifetime = new ResultCache(descriptor.Lifetime, serviceIdentifier, slot); Type closedType; try { - Type[] genericTypeArguments = serviceType.GenericTypeArguments; + Type[] genericTypeArguments = serviceIdentifier.ServiceType.GenericTypeArguments; if (ServiceProvider.VerifyAotCompatibility) { - VerifyOpenGenericAotCompatibility(serviceType, genericTypeArguments); + VerifyOpenGenericAotCompatibility(serviceIdentifier.ServiceType, genericTypeArguments); } closedType = descriptor.ImplementationType.MakeGenericType(genericTypeArguments); @@ -408,7 +440,7 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult return null; } - return _callSiteCache[callSiteKey] = CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain); + return _callSiteCache[callSiteKey] = CreateConstructorCallSite(lifetime, serviceIdentifier, closedType, callSiteChain); } return null; @@ -416,13 +448,13 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult private ConstructorCallSite CreateConstructorCallSite( ResultCache lifetime, - Type serviceType, + ServiceIdentifier serviceIdentifier, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, CallSiteChain callSiteChain) { try { - callSiteChain.Add(serviceType, implementationType); + callSiteChain.Add(serviceIdentifier, implementationType); ConstructorInfo[] constructors = implementationType.GetConstructors(); ServiceCallSite[]? parameterCallSites = null; @@ -437,16 +469,17 @@ private ConstructorCallSite CreateConstructorCallSite( ParameterInfo[] parameters = constructor.GetParameters(); if (parameters.Length == 0) { - return new ConstructorCallSite(lifetime, serviceType, constructor); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor); } parameterCallSites = CreateArgumentCallSites( + serviceIdentifier, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true)!; - return new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, constructor, parameterCallSites); } Array.Sort(constructors, @@ -459,6 +492,7 @@ private ConstructorCallSite CreateConstructorCallSite( ParameterInfo[] parameters = constructors[i].GetParameters(); ServiceCallSite[]? currentParameterCallSites = CreateArgumentCallSites( + serviceIdentifier, implementationType, callSiteChain, parameters, @@ -509,27 +543,48 @@ private ConstructorCallSite CreateConstructorCallSite( else { Debug.Assert(parameterCallSites != null); - return new ConstructorCallSite(lifetime, serviceType, bestConstructor, parameterCallSites); + return new ConstructorCallSite(lifetime, serviceIdentifier.ServiceType, bestConstructor, parameterCallSites); } } finally { - callSiteChain.Remove(serviceType); + callSiteChain.Remove(serviceIdentifier); } } /// Not null if throwIfCallSiteNotFound is true private ServiceCallSite[]? CreateArgumentCallSites( + ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound) { var parameterCallSites = new ServiceCallSite[parameters.Length]; + for (int index = 0; index < parameters.Length; index++) { + ServiceCallSite? callSite = null; Type parameterType = parameters[index].ParameterType; - ServiceCallSite? callSite = GetCallSite(parameterType, callSiteChain); + if (parameters[index].CustomAttributes != null) + { + foreach (var attribute in parameters[index].GetCustomAttributes(true)) + { + if (attribute is ServiceKeyAttribute) + { + callSite = new ConstantCallSite(parameterType, serviceIdentifier.ServiceKey); + break; + } + if (attribute is FromKeyedServicesAttribute keyed) + { + var parameterSvcId = new ServiceIdentifier(keyed.Key, parameterType); + callSite = GetCallSite(parameterSvcId, callSiteChain); + break; + } + } + } + + callSite ??= GetCallSite(ServiceIdentifier.FromServiceType(parameterType), callSiteChain); if (callSite == null && ParameterDefaultValue.TryGetDefaultValue(parameters[index], out object? defaultValue)) { @@ -573,13 +628,19 @@ private static void VerifyOpenGenericAotCompatibility(Type serviceType, Type[] g } } - public void Add(Type type, ServiceCallSite serviceCallSite) + public void Add(ServiceIdentifier serviceIdentifier, ServiceCallSite serviceCallSite) { - _callSiteCache[new ServiceCacheKey(type, DefaultSlot)] = serviceCallSite; + _callSiteCache[new ServiceCacheKey(serviceIdentifier, DefaultSlot)] = serviceCallSite; } - public bool IsService(Type serviceType) + public bool IsService(Type serviceType) => IsService(new ServiceIdentifier(null, serviceType)); + + public bool IsService(object key, Type serviceType) => IsService(new ServiceIdentifier(key, serviceType)); + + internal bool IsService(ServiceIdentifier serviceIdentifier) { + var serviceType = serviceIdentifier.ServiceType; + if (serviceType is null) { throw new ArgumentNullException(nameof(serviceType)); @@ -591,7 +652,12 @@ public bool IsService(Type serviceType) return false; } - if (_descriptorLookup.ContainsKey(serviceType)) + if (_descriptorLookup.ContainsKey(serviceIdentifier)) + { + return true; + } + + if (serviceIdentifier.ServiceKey != null && _descriptorLookup.ContainsKey(new ServiceIdentifier(KeyedService.AnyKey, serviceType))) { return true; } @@ -600,7 +666,7 @@ public bool IsService(Type serviceType) { // We special case IEnumerable since it isn't explicitly registered in the container // yet we can manifest instances of it when requested. - return genericDefinition == typeof(IEnumerable<>) || _descriptorLookup.ContainsKey(genericDefinition); + return genericDefinition == typeof(IEnumerable<>) || _descriptorLookup.ContainsKey(ServiceIdentifier.FromServiceType(genericDefinition)); } // These are the built in service types that aren't part of the list of service descriptors diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs index 3386987b077e7..f1fcd7a365d61 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs @@ -15,6 +15,13 @@ public FactoryCallSite(ResultCache cache, Type serviceType, Func factory) : base(cache) + { + // TODO BPETIT FIXEME + Factory = sp => factory(sp, serviceKey); + ServiceType = serviceType; + } + public override Type ServiceType { get; } public override Type? ImplementationType => null; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs index 345dce793d034..b085aef4906d9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.InteropServices; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { @@ -271,10 +272,13 @@ private static void AddConstant(ILEmitResolverBuilderContext argument, object? v private static void AddCacheKey(ILEmitResolverBuilderContext argument, ServiceCacheKey key) { - Debug.Assert(key.Type != null); + Debug.Assert(key.ServiceIdentifier != null); + var id = key.ServiceIdentifier.Value; // new ServiceCacheKey(typeof(key.Type), key.Slot) - argument.Generator.Emit(OpCodes.Ldtoken, key.Type); + // TODO BPETIT FIXME + AddConstant(argument, id.ServiceKey); + argument.Generator.Emit(OpCodes.Ldtoken, id.ServiceType); argument.Generator.Emit(OpCodes.Call, GetTypeFromHandleMethod); argument.Generator.Emit(OpCodes.Ldc_I4, key.Slot); argument.Generator.Emit(OpCodes.Newobj, CacheKeyCtor); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs index 5b4da78aaec11..6ba5da3352361 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ResultCache.cs @@ -10,7 +10,7 @@ internal struct ResultCache { public static ResultCache None(Type serviceType) { - var cacheKey = new ServiceCacheKey(serviceType, 0); + var cacheKey = new ServiceCacheKey(ServiceIdentifier.FromServiceType(serviceType), 0); return new ResultCache(CallSiteResultCacheLocation.None, cacheKey); } @@ -20,9 +20,9 @@ internal ResultCache(CallSiteResultCacheLocation lifetime, ServiceCacheKey cache Key = cacheKey; } - public ResultCache(ServiceLifetime lifetime, Type? type, int slot) + public ResultCache(ServiceLifetime lifetime, ServiceIdentifier? serviceIdentifier, int slot) { - Debug.Assert(lifetime == ServiceLifetime.Transient || type != null); + Debug.Assert(lifetime == ServiceLifetime.Transient || serviceIdentifier != null); switch (lifetime) { @@ -39,7 +39,7 @@ public ResultCache(ServiceLifetime lifetime, Type? type, int slot) Location = CallSiteResultCacheLocation.None; break; } - Key = new ServiceCacheKey(type, slot); + Key = new ServiceCacheKey(serviceIdentifier, slot); } public CallSiteResultCacheLocation Location { get; set; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs index 569fbef9de9bb..1c1574683fa55 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup /// /// Type of service being cached /// - public Type? Type { get; } + public ServiceIdentifier? ServiceIdentifier { get; } /// /// Reverse index of the service when resolved in IEnumerable<Type> where default instance gets slot 0. @@ -26,9 +26,15 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup /// public int Slot { get; } - public ServiceCacheKey(Type? type, int slot) + public ServiceCacheKey(object key, Type type, int slot) { - Type = type; + ServiceIdentifier = new ServiceIdentifier(key, type); + Slot = slot; + } + + public ServiceCacheKey(ServiceIdentifier? type, int slot) + { + ServiceIdentifier = type; Slot = slot; } @@ -36,7 +42,7 @@ public ServiceCacheKey(Type? type, int slot) /// An instance to compare with this instance. /// true if the current instance is equal to the other instance; otherwise, false. public bool Equals(ServiceCacheKey other) => - Type == other.Type && Slot == other.Slot; + ServiceIdentifier.Equals(other.ServiceIdentifier) && Slot == other.Slot; public override bool Equals([NotNullWhen(true)] object? obj) => obj is ServiceCacheKey other && Equals(other); @@ -45,7 +51,7 @@ public override int GetHashCode() { unchecked { - return ((Type?.GetHashCode() ?? 23) * 397) ^ Slot; + return ((ServiceIdentifier?.GetHashCode() ?? 23) * 397) ^ Slot; } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs new file mode 100644 index 0000000000000..2416ee27cc3b6 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.DependencyInjection.ServiceLookup +{ + internal readonly struct ServiceIdentifier : IEquatable + { + public object? ServiceKey { get; } + + public Type ServiceType { get; } + + public ServiceIdentifier(Type serviceType) + { + ServiceType = serviceType; + } + + public ServiceIdentifier(object? serviceKey, Type serviceType) + { + ServiceKey = serviceKey; + ServiceType = serviceType; + } + + public static ServiceIdentifier FromDescriptor(ServiceDescriptor serviceDescriptor) + => new ServiceIdentifier(serviceDescriptor.ServiceKey, serviceDescriptor.ServiceType); + + public static ServiceIdentifier FromServiceType(Type type) => new ServiceIdentifier(null, type); + + public bool Equals(ServiceIdentifier other) + { + if (ServiceKey == null && other.ServiceKey == null) + { + return ServiceType.Equals(other.ServiceType); + } + else if (ServiceKey != null && other.ServiceKey != null) + { + return ServiceType.Equals(other.ServiceType) && ServiceKey.Equals(other.ServiceKey); + } + return false; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is ServiceIdentifier && Equals((ServiceIdentifier)obj); + } + + public override int GetHashCode() + { + unchecked + { + if (ServiceKey == null) + { + return ServiceType.GetHashCode(); + } + return ((ServiceType?.GetHashCode() ?? 23) * 397) ^ ServiceKey.GetHashCode(); + } + } + + public bool IsConstructedGenericType => ServiceType.IsConstructedGenericType; + + public ServiceIdentifier GetGenericTypeDefinition() => new ServiceIdentifier(ServiceKey, ServiceType.GetGenericTypeDefinition()); + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs index ba68712645d3e..5ef37ba9be0c5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs @@ -47,7 +47,7 @@ public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope) ThrowHelper.ThrowObjectDisposedException(); } - return RootProvider.GetService(serviceType, this); + return RootProvider.GetService(ServiceIdentifier.FromServiceType(serviceType), this); } public IServiceProvider ServiceProvider => this; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index 2348fbde72e5d..f6143cc495e19 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -17,18 +17,18 @@ namespace Microsoft.Extensions.DependencyInjection /// [DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerTypeProxy(typeof(ServiceProviderDebugView))] - public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDisposable + public sealed class ServiceProvider : IServiceProvider, ISupportKeyedService, IDisposable, IAsyncDisposable { private readonly CallSiteValidator? _callSiteValidator; - private readonly Func> _createServiceAccessor; + private readonly Func> _createServiceAccessor; // Internal for testing internal ServiceProviderEngine _engine; private bool _disposed; - private readonly ConcurrentDictionary> _realizedServices; + private readonly ConcurrentDictionary> _realizedServices; internal CallSiteFactory CallSiteFactory { get; } @@ -50,14 +50,14 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv Root = new ServiceProviderEngineScope(this, isRootScope: true); _engine = GetEngine(); _createServiceAccessor = CreateServiceAccessor; - _realizedServices = new ConcurrentDictionary>(); + _realizedServices = new ConcurrentDictionary>(); CallSiteFactory = new CallSiteFactory(serviceDescriptors); // The list of built in services that aren't part of the list of service descriptors // keep this in sync with CallSiteFactory.IsService - CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite()); - CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root)); - CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory)); + CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceProvider)), new ServiceProviderCallSite()); + CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceScopeFactory)), new ConstantCallSite(typeof(IServiceScopeFactory), Root)); + CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceProviderIsService)), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory)); if (options.ValidateScopes) { @@ -94,7 +94,10 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// /// The type of the service to get. /// The service that was produced. - public object? GetService(Type serviceType) => GetService(serviceType, Root); + public object? GetService(Type serviceType) => GetService(ServiceIdentifier.FromServiceType(serviceType), Root); + + public object? GetKeyedService(Type serviceType, object serviceKey) + => GetService(new ServiceIdentifier(serviceKey, serviceType), Root); internal bool IsDisposed() => _disposed; @@ -128,16 +131,16 @@ private void OnResolve(ServiceCallSite callSite, IServiceScope scope) _callSiteValidator?.ValidateResolution(callSite, scope, Root); } - internal object? GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) + internal object? GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope) { if (_disposed) { ThrowHelper.ThrowObjectDisposedException(); } - Func realizedService = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor); + Func realizedService = _realizedServices.GetOrAdd(serviceIdentifier, _createServiceAccessor); var result = realizedService.Invoke(serviceProviderEngineScope); - System.Diagnostics.Debug.Assert(result is null || CallSiteFactory.IsService(serviceType)); + System.Diagnostics.Debug.Assert(result is null || CallSiteFactory.IsService(serviceIdentifier)); return result; } @@ -162,12 +165,12 @@ private void ValidateService(ServiceDescriptor descriptor) } } - private Func CreateServiceAccessor(Type serviceType) + private Func CreateServiceAccessor(ServiceIdentifier serviceIdentifier) { - ServiceCallSite? callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain()); + ServiceCallSite? callSite = CallSiteFactory.GetCallSite(serviceIdentifier, new CallSiteChain()); if (callSite != null) { - DependencyInjectionEventSource.Log.CallSiteBuilt(this, serviceType, callSite); + DependencyInjectionEventSource.Log.CallSiteBuilt(this, serviceIdentifier.ServiceType, callSite); OnCreate(callSite); // Optimize singleton case @@ -176,7 +179,7 @@ private void ValidateService(ServiceDescriptor descriptor) object? value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root); return scope => { - DependencyInjectionEventSource.Log.ServiceResolved(this, serviceType); + DependencyInjectionEventSource.Log.ServiceResolved(this, serviceIdentifier.ServiceType); return value; }; } @@ -185,7 +188,7 @@ private void ValidateService(ServiceDescriptor descriptor) return scope => { OnResolve(callSite, scope); - DependencyInjectionEventSource.Log.ServiceResolved(this, serviceType); + DependencyInjectionEventSource.Log.ServiceResolved(this, serviceIdentifier.ServiceType); return realizedService(scope); }; } @@ -195,7 +198,8 @@ private void ValidateService(ServiceDescriptor descriptor) internal void ReplaceServiceAccessor(ServiceCallSite callSite, Func accessor) { - _realizedServices[callSite.ServiceType] = accessor; + // TODO BPETIT + _realizedServices[ServiceIdentifier.FromServiceType(callSite.ServiceType)] = accessor; } internal IServiceScope CreateScope() diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs new file mode 100644 index 0000000000000..2bee1126934ee --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs @@ -0,0 +1,233 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Extensions.DependencyInjection.Tests +{ + public abstract class KeyedServiceProviderContainerTests + { + protected abstract IServiceProvider CreateServiceProvider(IServiceCollection collection); + + [Fact] + public void ResolveKeyedService() + { + var service1 = new Service(); + var service2 = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", service1); + serviceCollection.AddKeyedSingleton("service2", service2); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service1, provider.GetKeyedService("service1")); + Assert.Same(service2, provider.GetKeyedService("service2")); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstance() + { + var service = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", service); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service, provider.GetKeyedService("service1")); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithKeyInjection() + { + var serviceKey = "this-is-my-service"; + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(serviceKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var svc = provider.GetKeyedService(serviceKey); + Assert.NotNull(svc); + Assert.Equal(serviceKey, svc.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + + var serviceKey1 = "some-key"; + var svc1 = provider.GetKeyedService(serviceKey1); + Assert.NotNull(svc1); + Assert.Equal(serviceKey1, svc1.ToString()); + + var serviceKey2 = "some-other-key"; + var svc2 = provider.GetKeyedService(serviceKey2); + Assert.NotNull(svc2); + Assert.Equal(serviceKey2, svc2.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithKeyedParameter() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1"); + serviceCollection.AddKeyedSingleton("service2"); + serviceCollection.AddSingleton(); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var svc = provider.GetService(); + Assert.NotNull(svc); + Assert.Equal("service1", svc.Service1.ToString()); + Assert.Equal("service2", svc.Service2.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonFactory() + { + var service = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", (sp, key) => service); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service, provider.GetKeyedService("service1")); + } + + [Fact] + public void ResolveKeyedServiceSingletonFactoryWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, (sp, key) => new Service((string)key)); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + + for (int i=0; i<3; i++) + { + var key = "service" + i; + var s1 = provider.GetKeyedService(key); + var s2 = provider.GetKeyedService(key); + Assert.Same(s1, s2); + Assert.Equal(key, s1.ToString()); + } + } + + [Fact] + public void ResolveKeyedServiceSingletonType() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1"); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Equal(typeof(Service), provider.GetKeyedService("service1")!.GetType()); + } + + [Fact] + public void ResolveKeyedServiceTransientFactory() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient("service1", (sp, key) => new Service(key as string)); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + Assert.Equal("service1", first.ToString()); + Assert.Equal("service1", second.ToString()); + } + + [Fact] + public void ResolveKeyedServiceTransientType() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient("service1"); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + } + + [Fact] + public void ResolveKeyedServiceTransientTypeWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient(KeyedService.AnyKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + } + + interface IService { } + + class Service : IService + { + private readonly string _id; + + public Service() => _id = Guid.NewGuid().ToString(); + + public Service([ServiceKey] string id) => _id = id; + + public override string? ToString() => _id; + } + + class OtherService + { + public OtherService( + [FromKeyedServices("service1")] IService service1, + [FromKeyedServices("service2")] IService service2) + { + Service1 = service1; + Service2 = service2; + } + + public IService Service1 { get; } + + public IService Service2 { get; } + } + } + + public class KeyedServiceProviderDefaultContainerTests : KeyedServiceProviderContainerTests + { + protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.Default); + } + + public class KeyedServiceProviderDynamicContainerTests : KeyedServiceProviderContainerTests + { + protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(); + } + + public class KeyedServiceProviderExpressionContainerTests : KeyedServiceProviderContainerTests + { + protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.Expressions); + } + + public class KeyedServiceProviderILEmitContainerTests : KeyedServiceProviderContainerTests + { + protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.ILEmit); + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs index dbf4e7b561918..a342ba4bdd25d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs @@ -16,6 +16,15 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { + public static class TempExtensions + { + // TODO BPETIT REMOVE ME + internal static ServiceCallSite GetCallSite(this CallSiteFactory callSiteFactory, Type type, CallSiteChain callSiteChain) + { + return callSiteFactory.GetCallSite(ServiceIdentifier.FromServiceType(type), callSiteChain); + } + } + public class CallSiteFactoryTest { [Fact] @@ -789,7 +798,7 @@ public void CreateCallSite_EnumberableCachedAtLowestLevel(ServiceDescriptor[] de Assert.Equal(expectedLocation, callSite.Cache.Location); Assert.Equal(0, callSite.Cache.Key.Slot); - Assert.Equal(typeof(IEnumerable), callSite.Cache.Key.Type); + Assert.Equal(typeof(IEnumerable), callSite.Cache.Key.ServiceIdentifier.Value.ServiceType); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs index e801497236f0b..f3de8577f71a8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs @@ -14,7 +14,7 @@ public void DoubleDisposeWorks() { var provider = new ServiceProvider(new ServiceCollection(), ServiceProviderOptions.Default); var serviceProviderEngineScope = new ServiceProviderEngineScope(provider, isRootScope: true); - serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null); + serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(ServiceIdentifier.FromServiceType(typeof(IFakeService)), 0), null); serviceProviderEngineScope.Dispose(); serviceProviderEngineScope.Dispose(); } diff --git a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml b/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml index 8969e45b4ad4b..cae5310ec6d31 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0004 From c26941c90c320be340530e9d9ef287cfa4e7ccf6 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 9 Jun 2023 14:25:53 +0200 Subject: [PATCH 02/43] Remove unecessary CompatibilitySuppressions.xml --- .../src/CompatibilitySuppressions.xml | 100 ------------------ 1 file changed, 100 deletions(-) delete mode 100644 src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml diff --git a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml deleted file mode 100644 index 80a467cc1f51f..0000000000000 --- a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - CP0001 - T:System.Collections.Generic.IAsyncEnumerable`1 - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Collections.Generic.IAsyncEnumerator`1 - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.IAsyncDisposable - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.AsyncIteratorMethodBuilder - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.ConfiguredAsyncDisposable - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Threading.Tasks.TaskAsyncEnumerableExtensions - ref/net462/Microsoft.Bcl.AsyncInterfaces.dll - lib/net462/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Collections.Generic.IAsyncEnumerable`1 - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Collections.Generic.IAsyncEnumerator`1 - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.IAsyncDisposable - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.AsyncIteratorMethodBuilder - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.ConfiguredAsyncDisposable - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - - CP0001 - T:System.Threading.Tasks.TaskAsyncEnumerableExtensions - ref/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - - \ No newline at end of file From e165c2e8723c9f949e9e9ce196fcdcd5a221d841 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 9 Jun 2023 14:31:44 +0200 Subject: [PATCH 03/43] Remove some TODO --- .../src/ServiceLookup/CallSiteFactory.cs | 1 - .../src/ServiceLookup/FactoryCallSite.cs | 1 - .../src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 81c995f209447..431c40b35d6ed 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -381,7 +381,6 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult } else if (descriptor.KeyedImplementationFactory != null) { - // TODO BPETIT FIXEME callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, serviceIdentifier.ServiceKey!, descriptor.KeyedImplementationFactory); } else if (descriptor.ImplementationType != null) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs index f1fcd7a365d61..e7fea17a46cb9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/FactoryCallSite.cs @@ -17,7 +17,6 @@ public FactoryCallSite(ResultCache cache, Type serviceType, Func factory) : base(cache) { - // TODO BPETIT FIXEME Factory = sp => factory(sp, serviceKey); ServiceType = serviceType; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs index b085aef4906d9..136d3cf0fb918 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs @@ -275,8 +275,7 @@ private static void AddCacheKey(ILEmitResolverBuilderContext argument, ServiceCa Debug.Assert(key.ServiceIdentifier != null); var id = key.ServiceIdentifier.Value; - // new ServiceCacheKey(typeof(key.Type), key.Slot) - // TODO BPETIT FIXME + // new ServiceCacheKey(key.ServiceKey, key.type, key.slot) AddConstant(argument, id.ServiceKey); argument.Generator.Emit(OpCodes.Ldtoken, id.ServiceType); argument.Generator.Emit(OpCodes.Call, GetTypeFromHandleMethod); From 6fc500f36335638bf81ebfe91022283b9eebcb91 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 9 Jun 2023 14:38:26 +0200 Subject: [PATCH 04/43] Minor test cleanup --- .../tests/DI.Tests/CallSiteTests.cs | 12 ++++++++++-- .../DI.Tests/ServiceLookup/CallSiteFactoryTest.cs | 11 +---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs index fa72121e67dc9..26b410e7f59d7 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs @@ -11,6 +11,14 @@ namespace Microsoft.Extensions.DependencyInjection.Tests { + internal static class CallSiteTestsExtensions + { + internal static ServiceCallSite GetCallSite(this CallSiteFactory callSiteFactory, Type type, CallSiteChain callSiteChain) + { + return callSiteFactory.GetCallSite(ServiceIdentifier.FromServiceType(type), callSiteChain); + } + } + public class CallSiteTests { public static IEnumerable TestServiceDescriptors(ServiceLifetime lifetime) @@ -136,7 +144,7 @@ public void BuildExpressionAddsDisposableCaptureForDisposableServices(ServiceLif var disposables = new List(); var provider = new ServiceProvider(descriptors, ServiceProviderOptions.Default); - + var callSite = provider.CallSiteFactory.GetCallSite(typeof(ServiceC), new CallSiteChain()); var compiledCallSite = CompileCallSite(callSite, provider); @@ -185,7 +193,7 @@ public void BuildExpressionElidesDisposableCaptureForNonDisposableServices(Servi var disposables = new List(); var provider = new ServiceProvider(descriptors, ServiceProviderOptions.Default); - + var callSite = provider.CallSiteFactory.GetCallSite(typeof(ServiceC), new CallSiteChain()); var compiledCallSite = CompileCallSite(callSite, provider); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs index a342ba4bdd25d..ade998a732042 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs @@ -16,15 +16,6 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - public static class TempExtensions - { - // TODO BPETIT REMOVE ME - internal static ServiceCallSite GetCallSite(this CallSiteFactory callSiteFactory, Type type, CallSiteChain callSiteChain) - { - return callSiteFactory.GetCallSite(ServiceIdentifier.FromServiceType(type), callSiteChain); - } - } - public class CallSiteFactoryTest { [Fact] @@ -1010,7 +1001,7 @@ private static Func GetCallSiteFactory(params ServiceDesc var callSiteFactory = new CallSiteFactory(collection.ToArray()); - return type => callSiteFactory.GetCallSite(type, new CallSiteChain()); + return type => callSiteFactory.GetCallSite(ServiceIdentifier.FromServiceType(type), new CallSiteChain()); } private static IEnumerable GetParameters(ConstructorCallSite constructorCallSite) => From bdc6bfbe648ca2fbea4b7bdc00eefc513458bef2 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 9 Jun 2023 14:44:54 +0200 Subject: [PATCH 05/43] Set error message for non keyed service provider --- .../src/Resources/Strings.resx | 3 +++ .../src/ServiceProviderKeyedServiceExtensions.cs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx index bfe0f89909ad3..30021e2cc716d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx @@ -167,4 +167,7 @@ Multiple constructors accepting all given argument types have been found in type '{0}'. There should only be one applicable constructor. {0} = instance type + + This service provider doesn't support keyed services. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs index 2da454c61e01d..6c89797486ede 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs @@ -28,7 +28,7 @@ public static class ServiceProviderKeyedServiceExtensions return (T?)keyedServiceProvider.GetKeyedService(typeof(T), serviceKey); } - throw new InvalidOperationException("TODO BPETIT"); + throw new InvalidOperationException(SR.KeyedServicesNotSupported); } /// @@ -59,7 +59,7 @@ public static object GetRequiredKeyedService(this IServiceProvider provider, Typ return service; } - throw new InvalidOperationException("TODO BPETIT"); + throw new InvalidOperationException(SR.KeyedServicesNotSupported); } /// From b0152ac69bdaa4f76a1478aca2341312e916e2ea Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 19 Jun 2023 15:26:45 +0200 Subject: [PATCH 06/43] Move tests to Specification.Tests --- ...edDependencyInjectionSpecificationTests.cs | 212 ++++++++++++++++++ .../KeyedServiceProviderContainerTests.cs | 212 +----------------- 2 files changed, 217 insertions(+), 207 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs new file mode 100644 index 0000000000000..5e88392daa941 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -0,0 +1,212 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +namespace Microsoft.Extensions.DependencyInjection.Specification +{ + public abstract partial class KeyedDependencyInjectionSpecificationTests + { + protected abstract IServiceProvider CreateServiceProvider(IServiceCollection collection); + + [Fact] + public void ResolveKeyedService() + { + var service1 = new Service(); + var service2 = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", service1); + serviceCollection.AddKeyedSingleton("service2", service2); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service1, provider.GetKeyedService("service1")); + Assert.Same(service2, provider.GetKeyedService("service2")); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstance() + { + var service = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", service); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service, provider.GetKeyedService("service1")); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithKeyInjection() + { + var serviceKey = "this-is-my-service"; + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(serviceKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var svc = provider.GetKeyedService(serviceKey); + Assert.NotNull(svc); + Assert.Equal(serviceKey, svc.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + + var serviceKey1 = "some-key"; + var svc1 = provider.GetKeyedService(serviceKey1); + Assert.NotNull(svc1); + Assert.Equal(serviceKey1, svc1.ToString()); + + var serviceKey2 = "some-other-key"; + var svc2 = provider.GetKeyedService(serviceKey2); + Assert.NotNull(svc2); + Assert.Equal(serviceKey2, svc2.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonInstanceWithKeyedParameter() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1"); + serviceCollection.AddKeyedSingleton("service2"); + serviceCollection.AddSingleton(); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var svc = provider.GetService(); + Assert.NotNull(svc); + Assert.Equal("service1", svc.Service1.ToString()); + Assert.Equal("service2", svc.Service2.ToString()); + } + + [Fact] + public void ResolveKeyedServiceSingletonFactory() + { + var service = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1", (sp, key) => service); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Same(service, provider.GetKeyedService("service1")); + } + + [Fact] + public void ResolveKeyedServiceSingletonFactoryWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, (sp, key) => new Service((string)key)); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + + for (int i=0; i<3; i++) + { + var key = "service" + i; + var s1 = provider.GetKeyedService(key); + var s2 = provider.GetKeyedService(key); + Assert.Same(s1, s2); + Assert.Equal(key, s1.ToString()); + } + } + + [Fact] + public void ResolveKeyedServiceSingletonType() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("service1"); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.Equal(typeof(Service), provider.GetKeyedService("service1")!.GetType()); + } + + [Fact] + public void ResolveKeyedServiceTransientFactory() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient("service1", (sp, key) => new Service(key as string)); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + Assert.Equal("service1", first.ToString()); + Assert.Equal("service1", second.ToString()); + } + + [Fact] + public void ResolveKeyedServiceTransientType() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient("service1"); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + } + + [Fact] + public void ResolveKeyedServiceTransientTypeWithAnyKey() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient(KeyedService.AnyKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var first = provider.GetKeyedService("service1"); + var second = provider.GetKeyedService("service1"); + Assert.NotSame(first, second); + } + + internal interface IService { } + + internal class Service : IService + { + private readonly string _id; + + public Service() => _id = Guid.NewGuid().ToString(); + + public Service([ServiceKey] string id) => _id = id; + + public override string? ToString() => _id; + } + + internal class OtherService + { + public OtherService( + [FromKeyedServices("service1")] IService service1, + [FromKeyedServices("service2")] IService service2) + { + Service1 = service1; + Service2 = service2; + } + + public IService Service1 { get; } + + public IService Service2 { get; } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs index 2bee1126934ee..27dda2f2b4ffb 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs @@ -3,230 +3,28 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection.Specification; using Xunit; namespace Microsoft.Extensions.DependencyInjection.Tests { - public abstract class KeyedServiceProviderContainerTests - { - protected abstract IServiceProvider CreateServiceProvider(IServiceCollection collection); - - [Fact] - public void ResolveKeyedService() - { - var service1 = new Service(); - var service2 = new Service(); - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton("service1", service1); - serviceCollection.AddKeyedSingleton("service2", service2); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - Assert.Same(service1, provider.GetKeyedService("service1")); - Assert.Same(service2, provider.GetKeyedService("service2")); - } - - [Fact] - public void ResolveKeyedServiceSingletonInstance() - { - var service = new Service(); - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton("service1", service); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - Assert.Same(service, provider.GetKeyedService("service1")); - } - - [Fact] - public void ResolveKeyedServiceSingletonInstanceWithKeyInjection() - { - var serviceKey = "this-is-my-service"; - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton(serviceKey); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - var svc = provider.GetKeyedService(serviceKey); - Assert.NotNull(svc); - Assert.Equal(serviceKey, svc.ToString()); - } - - [Fact] - public void ResolveKeyedServiceSingletonInstanceWithAnyKey() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton(KeyedService.AnyKey); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - - var serviceKey1 = "some-key"; - var svc1 = provider.GetKeyedService(serviceKey1); - Assert.NotNull(svc1); - Assert.Equal(serviceKey1, svc1.ToString()); - - var serviceKey2 = "some-other-key"; - var svc2 = provider.GetKeyedService(serviceKey2); - Assert.NotNull(svc2); - Assert.Equal(serviceKey2, svc2.ToString()); - } - - [Fact] - public void ResolveKeyedServiceSingletonInstanceWithKeyedParameter() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton("service1"); - serviceCollection.AddKeyedSingleton("service2"); - serviceCollection.AddSingleton(); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - var svc = provider.GetService(); - Assert.NotNull(svc); - Assert.Equal("service1", svc.Service1.ToString()); - Assert.Equal("service2", svc.Service2.ToString()); - } - - [Fact] - public void ResolveKeyedServiceSingletonFactory() - { - var service = new Service(); - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton("service1", (sp, key) => service); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - Assert.Same(service, provider.GetKeyedService("service1")); - } - - [Fact] - public void ResolveKeyedServiceSingletonFactoryWithAnyKey() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton(KeyedService.AnyKey, (sp, key) => new Service((string)key)); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - - for (int i=0; i<3; i++) - { - var key = "service" + i; - var s1 = provider.GetKeyedService(key); - var s2 = provider.GetKeyedService(key); - Assert.Same(s1, s2); - Assert.Equal(key, s1.ToString()); - } - } - - [Fact] - public void ResolveKeyedServiceSingletonType() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedSingleton("service1"); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - Assert.Equal(typeof(Service), provider.GetKeyedService("service1")!.GetType()); - } - - [Fact] - public void ResolveKeyedServiceTransientFactory() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedTransient("service1", (sp, key) => new Service(key as string)); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - var first = provider.GetKeyedService("service1"); - var second = provider.GetKeyedService("service1"); - Assert.NotSame(first, second); - Assert.Equal("service1", first.ToString()); - Assert.Equal("service1", second.ToString()); - } - - [Fact] - public void ResolveKeyedServiceTransientType() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedTransient("service1"); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - var first = provider.GetKeyedService("service1"); - var second = provider.GetKeyedService("service1"); - Assert.NotSame(first, second); - } - - [Fact] - public void ResolveKeyedServiceTransientTypeWithAnyKey() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddKeyedTransient(KeyedService.AnyKey); - - var provider = CreateServiceProvider(serviceCollection); - - Assert.Null(provider.GetService()); - var first = provider.GetKeyedService("service1"); - var second = provider.GetKeyedService("service1"); - Assert.NotSame(first, second); - } - - interface IService { } - - class Service : IService - { - private readonly string _id; - - public Service() => _id = Guid.NewGuid().ToString(); - - public Service([ServiceKey] string id) => _id = id; - - public override string? ToString() => _id; - } - - class OtherService - { - public OtherService( - [FromKeyedServices("service1")] IService service1, - [FromKeyedServices("service2")] IService service2) - { - Service1 = service1; - Service2 = service2; - } - - public IService Service1 { get; } - - public IService Service2 { get; } - } - } - public class KeyedServiceProviderDefaultContainerTests : KeyedServiceProviderContainerTests + public class KeyedServiceProviderDefaultContainerTests : KeyedDependencyInjectionSpecificationTests { protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.Default); } - public class KeyedServiceProviderDynamicContainerTests : KeyedServiceProviderContainerTests + public class KeyedServiceProviderDynamicContainerTests : KeyedDependencyInjectionSpecificationTests { protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(); } - public class KeyedServiceProviderExpressionContainerTests : KeyedServiceProviderContainerTests + public class KeyedServiceProviderExpressionContainerTests : KeyedDependencyInjectionSpecificationTests { protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.Expressions); } - public class KeyedServiceProviderILEmitContainerTests : KeyedServiceProviderContainerTests + public class KeyedServiceProviderILEmitContainerTests : KeyedDependencyInjectionSpecificationTests { protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.ILEmit); } From 57c62f76d17995854551247ba275d94f7c3c7e1f Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 19 Jun 2023 15:42:33 +0200 Subject: [PATCH 07/43] Add open generic test --- ...eyedDependencyInjectionSpecificationTests.cs | 17 +++++++++++++++++ .../src/ServiceLookup/CallSiteFactory.cs | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 5e88392daa941..03878cc1753a8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -3,6 +3,7 @@ using System; using Xunit; +using Microsoft.Extensions.DependencyInjection.Specification.Fakes; namespace Microsoft.Extensions.DependencyInjection.Specification { @@ -26,6 +27,22 @@ public void ResolveKeyedService() Assert.Same(service2, provider.GetKeyedService("service2")); } + [Fact] + public void ResolveKeyedOpenGenericService() + { + var collection = new ServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeOpenGenericService<>), "my-service", typeof(FakeOpenGenericService<>)); + collection.AddSingleton(); + var provider = CreateServiceProvider(collection); + + // Act + var genericService = provider.GetKeyedService>("my-service"); + var singletonService = provider.GetService(); + + // Assert + Assert.Same(singletonService, genericService.Value); + } + [Fact] public void ResolveKeyedServiceSingletonInstance() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 431c40b35d6ed..dd0a04dceb4c9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -665,7 +665,7 @@ internal bool IsService(ServiceIdentifier serviceIdentifier) { // We special case IEnumerable since it isn't explicitly registered in the container // yet we can manifest instances of it when requested. - return genericDefinition == typeof(IEnumerable<>) || _descriptorLookup.ContainsKey(ServiceIdentifier.FromServiceType(genericDefinition)); + return genericDefinition == typeof(IEnumerable<>) || _descriptorLookup.ContainsKey(serviceIdentifier.GetGenericTypeDefinition()); } // These are the built in service types that aren't part of the list of service descriptors From e741b3ef8dc3e8750e34a6897e358615fbd7c659 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 20 Jun 2023 15:06:36 +0200 Subject: [PATCH 08/43] dirty fix for ReplaceServiceAccessor --- .../src/ServiceLookup/CallSiteFactory.cs | 1 + .../src/ServiceLookup/ServiceCallSite.cs | 1 + .../src/ServiceProvider.cs | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index dd0a04dceb4c9..c6d7d30d97c4c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -391,6 +391,7 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult { throw new InvalidOperationException(SR.InvalidServiceDescriptor); } + callSite.Key = descriptor.ServiceKey; return _callSiteCache[callSiteKey] = callSite; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs index 1ede82e09c914..e3ff3baa81859 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCallSite.cs @@ -20,6 +20,7 @@ protected ServiceCallSite(ResultCache cache) public abstract CallSiteKind Kind { get; } public ResultCache Cache { get; } public object? Value { get; set; } + public object? Key { get; set; } public bool CaptureDisposable => ImplementationType == null || diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index f6143cc495e19..8576048b25a39 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -198,8 +198,7 @@ private void ValidateService(ServiceDescriptor descriptor) internal void ReplaceServiceAccessor(ServiceCallSite callSite, Func accessor) { - // TODO BPETIT - _realizedServices[ServiceIdentifier.FromServiceType(callSite.ServiceType)] = accessor; + _realizedServices[new ServiceIdentifier(callSite.Key, callSite.ServiceType)] = accessor; } internal IServiceScope CreateScope() From 3c228f143059f2d8b0c05b213e480a1331499c01 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 20 Jun 2023 15:51:48 +0200 Subject: [PATCH 09/43] Add enumeration tests + fixes --- ...edDependencyInjectionSpecificationTests.cs | 63 +++++++++++++++++++ .../src/ServiceLookup/CallSiteFactory.cs | 30 +++++++-- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 03878cc1753a8..897c08af57cec 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -4,6 +4,7 @@ using System; using Xunit; using Microsoft.Extensions.DependencyInjection.Specification.Fakes; +using System.Linq; namespace Microsoft.Extensions.DependencyInjection.Specification { @@ -43,6 +44,52 @@ public void ResolveKeyedOpenGenericService() Assert.Same(singletonService, genericService.Value); } + [Fact] + public void ResolveKeyedServices() + { + var service1 = new Service(); + var service2 = new Service(); + var service3 = new Service(); + var service4 = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton("first-service", service1); + serviceCollection.AddKeyedSingleton("service", service2); + serviceCollection.AddKeyedSingleton("service", service3); + serviceCollection.AddKeyedSingleton("service", service4); + + var provider = CreateServiceProvider(serviceCollection); + + var firstSvc = provider.GetKeyedServices("first-service").ToList(); + Assert.Single(firstSvc); + Assert.Same(service1, firstSvc[0]); + + var services = provider.GetKeyedServices("service").ToList(); + Assert.Equal(new[] { service2, service3, service4 }, services); + } + + [Fact] + public void ResolveKeyedGenericServices() + { + var service1 = new FakeService(); + var service2 = new FakeService(); + var service3 = new FakeService(); + var service4 = new FakeService(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton>("first-service", service1); + serviceCollection.AddKeyedSingleton>("service", service2); + serviceCollection.AddKeyedSingleton>("service", service3); + serviceCollection.AddKeyedSingleton>("service", service4); + + var provider = CreateServiceProvider(serviceCollection); + + var firstSvc = provider.GetKeyedServices>("first-service").ToList(); + Assert.Single(firstSvc); + Assert.Same(service1, firstSvc[0]); + + var services = provider.GetKeyedServices>("service").ToList(); + Assert.Equal(new[] { service2, service3, service4 }, services); + } + [Fact] public void ResolveKeyedServiceSingletonInstance() { @@ -92,6 +139,22 @@ public void ResolveKeyedServiceSingletonInstanceWithAnyKey() Assert.Equal(serviceKey2, svc2.ToString()); } + [Fact] + public void ResolveKeyedServicesSingletonInstanceWithAnyKey() + { + var service1 = new FakeService(); + var service2 = new FakeService(); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton>(KeyedService.AnyKey, service1); + serviceCollection.AddKeyedSingleton>("some-key", service2); + + var provider = CreateServiceProvider(serviceCollection); + + var services = provider.GetKeyedServices>("some-key").ToList(); + Assert.Equal(new[] { service1, service2 }, services); + } + [Fact] public void ResolveKeyedServiceSingletonInstanceWithKeyedParameter() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index c6d7d30d97c4c..9df9c286bcf22 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -272,7 +272,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica } Type itemType = serviceType.GenericTypeArguments[0]; - var cacheKey = ServiceIdentifier.FromServiceType(itemType); + var cacheKey = new ServiceIdentifier(serviceIdentifier.ServiceKey, itemType); if (ServiceProvider.VerifyAotCompatibility && itemType.IsValueType) { // NativeAOT apps are not able to make Enumerable of ValueType services @@ -315,16 +315,22 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica int slot = 0; for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite) + if (KeyEquals(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) { - AddCallSite(callSite, i); + if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite) + { + AddCallSite(callSite, i); + } } } for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (TryCreateOpenGeneric(_descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) + if (KeyEquals(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) { - AddCallSite(callSite, i); + if (TryCreateOpenGeneric(_descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) + { + AddCallSite(callSite, i); + } } } @@ -676,6 +682,20 @@ internal bool IsService(ServiceIdentifier serviceIdentifier) serviceType == typeof(IServiceProviderIsService); } + /// + /// Returns true if both keys are null or equals, or if key1 is KeyedService.AnyKey and key2 is not null + /// + private static bool KeyEquals(object? key1, object? key2) + { + if (key1 == null && key2 == null) + return true; + + if (key1 != null && key2 != null) + return key1.Equals(KeyedService.AnyKey) || key1.Equals(key2); + + return false; + } + private struct ServiceDescriptorCacheItem { [DisallowNull] From f84c8a149ffd930b54cf7628b23493cea953739a Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 17:29:43 +0200 Subject: [PATCH 10/43] Add custom ToString() to KeyedService.AnyKey --- .../src/ISupportKeyedService.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs index 25ed579f07fe5..8cf4c12232f1b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs @@ -18,6 +18,11 @@ public interface ISupportKeyedService public static class KeyedService { - public static object AnyKey { get; } = new object(); + public static object AnyKey { get; } = new AnyKeyObj(); + + private class AnyKeyObj + { + public override string? ToString() => "*"; + } } } From ddc7459fc6cb3cad4495dd06cb52241c2e071ef1 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 17:30:03 +0200 Subject: [PATCH 11/43] Fix CallSiteValidator --- .../src/ServiceLookup/CallSiteValidator.cs | 6 +++--- .../src/ServiceLookup/ServiceDescriptorCacheKey.cs | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs index f228507a6b8ab..f979f14745f88 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteValidator.cs @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteValidator: CallSiteVisitor + internal sealed class CallSiteValidator : CallSiteVisitor { // Keys are services being resolved via GetService, values - first scoped service in their call site tree private readonly ConcurrentDictionary _scopedServices = new ConcurrentDictionary(); @@ -30,13 +30,13 @@ public void ValidateResolution(ServiceCallSite callSite, IServiceScope scope, IS if (serviceType == scopedService) { throw new InvalidOperationException( - SR.Format(SR.DirectScopedResolvedFromRootException, serviceType, + SR.Format(SR.DirectScopedResolvedFromRootException, callSite.ServiceType, nameof(ServiceLifetime.Scoped).ToLowerInvariant())); } throw new InvalidOperationException( SR.Format(SR.ScopedResolvedFromRootException, - serviceType, + callSite.ServiceType, scopedService, nameof(ServiceLifetime.Scoped).ToLowerInvariant())); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs index 2416ee27cc3b6..c6d6d8fb0e4e1 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs @@ -61,5 +61,13 @@ public override int GetHashCode() public bool IsConstructedGenericType => ServiceType.IsConstructedGenericType; public ServiceIdentifier GetGenericTypeDefinition() => new ServiceIdentifier(ServiceKey, ServiceType.GetGenericTypeDefinition()); + + public override string? ToString() + { + if (ServiceKey == null) + return ServiceType.ToString(); + + return $"({ServiceKey}, {ServiceType})"; + } } } From 18f4879dce7128be4b0d1e7cd67ca2f5f56f459c Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 17:36:46 +0200 Subject: [PATCH 12/43] Merge ISupportRequiredKeyedService and ISupportKeyedService --- ...nsions.DependencyInjection.Abstractions.cs | 3 --- .../src/ISupportKeyedService.cs | 10 ++++++++ .../src/ISupportRequiredKeyedService.cs | 24 ------------------- .../ServiceProviderKeyedServiceExtensions.cs | 12 +--------- .../ServiceDescriptorCacheKey.cs | 2 ++ 5 files changed, 13 insertions(+), 38 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index f25e810c78fd8..b55f19a201542 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -58,9 +58,6 @@ public partial interface IServiceScopeFactory public partial interface ISupportKeyedService { object? GetKeyedService(System.Type serviceType, object serviceKey); - } - public partial interface ISupportRequiredKeyedService - { object GetRequiredKeyedService(System.Type serviceType, object serviceKey); } public partial interface ISupportRequiredService diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs index 8cf4c12232f1b..b013e7d45d43e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs @@ -14,6 +14,16 @@ public interface ISupportKeyedService /// An object that specifies the key of service object to get. /// A service object of type serviceType. -or- null if there is no service object of type serviceType. object? GetKeyedService(Type serviceType, object serviceKey); + + /// + /// Gets service of type from the implementing + /// this interface. + /// + /// An object that specifies the type of service object to get. + /// The of the service. + /// A service object of type . + /// Throws an exception if the cannot create the object. + object GetRequiredKeyedService(Type serviceType, object serviceKey); } public static class KeyedService diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs deleted file mode 100644 index c4d398ee1c08f..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportRequiredKeyedService.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Optional contract used by - /// to resolve services if supported by . - /// - public interface ISupportRequiredKeyedService - { - /// - /// Gets service of type from the implementing - /// this interface. - /// - /// An object that specifies the type of service object to get. - /// The of the service. - /// A service object of type . - /// Throws an exception if the cannot create the object. - object GetRequiredKeyedService(Type serviceType, object serviceKey); - } -} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs index 6c89797486ede..f4f013ffbe7b7 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs @@ -44,21 +44,11 @@ public static object GetRequiredKeyedService(this IServiceProvider provider, Typ ThrowHelper.ThrowIfNull(provider); ThrowHelper.ThrowIfNull(serviceType); - if (provider is ISupportRequiredKeyedService requiredServiceSupportingProvider) + if (provider is ISupportKeyedService requiredServiceSupportingProvider) { return requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey); } - if (provider is ISupportKeyedService keyedServiceProvider) - { - object? service = keyedServiceProvider.GetKeyedService(serviceType, serviceKey); - if (service == null) - { - throw new InvalidOperationException(SR.Format(SR.NoServiceRegistered, serviceType)); - } - return service; - } - throw new InvalidOperationException(SR.KeyedServicesNotSupported); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs index c6d6d8fb0e4e1..05e397b19cdb3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs @@ -65,7 +65,9 @@ public override int GetHashCode() public override string? ToString() { if (ServiceKey == null) + { return ServiceType.ToString(); + } return $"({ServiceKey}, {ServiceType})"; } From 3fa39b028cad4858531aa04b806e46d1455e8a41 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 18:16:48 +0200 Subject: [PATCH 13/43] Merge ISupportRequiredKeyedService and ISupportKeyedService --- .../ref/Microsoft.Extensions.DependencyInjection.cs | 3 +++ .../src/Resources/Strings.resx | 3 +++ .../src/ServiceProvider.cs | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index 76fa03d55a66b..cb4c856981040 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System; + namespace Microsoft.Extensions.DependencyInjection { public partial class DefaultServiceProviderFactory : Microsoft.Extensions.DependencyInjection.IServiceProviderFactory @@ -25,6 +27,7 @@ internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public object GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } + public object GetRequiredKeyedService(Type serviceType, object serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx index a81b637ecf6b2..ee997b2c5bdb9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx @@ -186,4 +186,7 @@ Unable to create a generic service for type '{0}' because '{1}' is a ValueType. Native code to support creating generic services might not be available with native AOT. + + No service for type '{0}' has been registered. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index 8576048b25a39..aa3985064ec02 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -99,6 +99,16 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv public object? GetKeyedService(Type serviceType, object serviceKey) => GetService(new ServiceIdentifier(serviceKey, serviceType), Root); + public object GetRequiredKeyedService(Type serviceType, object serviceKey) + { + object? service = GetKeyedService(serviceType, serviceKey); + if (service == null) + { + throw new InvalidOperationException(SR.Format(SR.NoServiceRegistered, serviceType)); + } + return service; + } + internal bool IsDisposed() => _disposed; /// From 8b58809bb87dd193444a912f57204825455c9b5e Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 18:20:13 +0200 Subject: [PATCH 14/43] Fix ServiceCollectionDescriptorExtensions.TryAdd --- .../src/Extensions/ServiceCollectionDescriptorExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs index 0ec8690594060..561893a093732 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs @@ -66,7 +66,8 @@ public static void TryAdd( int count = collection.Count; for (int i = 0; i < count; i++) { - if (collection[i].ServiceType == descriptor.ServiceType) + if (collection[i].ServiceType == descriptor.ServiceType + && collection[i].ServiceKey == descriptor.ServiceKey) { // Already added return; From 0d17ace677e0f269523523988035c50880a2df75 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 19:49:35 +0200 Subject: [PATCH 15/43] Fix in ServiceCollectionDescriptorExtensions --- .../Extensions/ServiceCollectionDescriptorExtensions.cs | 7 ++++--- .../ref/Microsoft.Extensions.DependencyInjection.cs | 6 ++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs index 561893a093732..f2bee7f56c472 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs @@ -473,7 +473,8 @@ public static void TryAddEnumerable( { ServiceDescriptor service = services[i]; if (service.ServiceType == descriptor.ServiceType && - service.GetImplementationType() == implementationType) + service.GetImplementationType() == implementationType && + service.ServiceKey == descriptor.ServiceKey) { // Already added return; @@ -531,7 +532,7 @@ public static IServiceCollection Replace( int count = collection.Count; for (int i = 0; i < count; i++) { - if (collection[i].ServiceType == descriptor.ServiceType) + if (collection[i].ServiceType == descriptor.ServiceType && collection[i].ServiceKey == descriptor.ServiceKey) { collection.RemoveAt(i); break; @@ -565,7 +566,7 @@ public static IServiceCollection RemoveAll(this IServiceCollection collection, T for (int i = collection.Count - 1; i >= 0; i--) { ServiceDescriptor? descriptor = collection[i]; - if (descriptor.ServiceType == serviceType) + if (descriptor.ServiceType == serviceType && descriptor.ServiceKey == null) { collection.RemoveAt(i); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index cb4c856981040..c0982ef4f34e9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -4,8 +4,6 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System; - namespace Microsoft.Extensions.DependencyInjection { public partial class DefaultServiceProviderFactory : Microsoft.Extensions.DependencyInjection.IServiceProviderFactory @@ -26,8 +24,8 @@ public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInj internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public object GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } - public object GetRequiredKeyedService(Type serviceType, object serviceKey) { throw null; } + public object? GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } + public object GetRequiredKeyedService(System.Type serviceType, object serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions From 68c3d7171369ffba7792c70f0bdd267d802b764b Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 20:08:55 +0200 Subject: [PATCH 16/43] Add IServiceProviderIsServiceKeyed --- ...oft.Extensions.DependencyInjection.Abstractions.cs | 4 ++++ .../src/IServiceProviderIsService.cs | 11 +++++++++++ .../src/ServiceLookup/CallSiteFactory.cs | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index b55f19a201542..ac76f0499015f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -47,6 +47,10 @@ public partial interface IServiceProviderIsService { bool IsService(System.Type serviceType); } + public partial interface IServiceProviderIsServiceKeyed + { + bool IsService(System.Type serviceType, object serviceKey); + } public partial interface IServiceScope : System.IDisposable { System.IServiceProvider ServiceProvider { get; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs index b24ab154d16e9..954295ca3d6aa 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs @@ -17,4 +17,15 @@ public interface IServiceProviderIsService /// true if the specified service is a available, false if it is not. bool IsService(Type serviceType); } + + public interface IServiceProviderIsServiceKeyed + { + /// + /// Determines if the specified service type is available from the . + /// + /// An object that specifies the type of service object to test. + /// The of the service. + /// true if the specified service is a available, false if it is not. + bool IsService(Type serviceType, object serviceKey); + } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 9df9c286bcf22..72a5d508badde 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteFactory : IServiceProviderIsService + internal sealed class CallSiteFactory : IServiceProviderIsService, IServiceProviderIsServiceKeyed { private const int DefaultSlot = 0; private readonly ServiceDescriptor[] _descriptors; From 38574c6c95f762b374bb34473886315b7a40e2e7 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Thu, 22 Jun 2023 20:54:25 +0200 Subject: [PATCH 17/43] Add IServiceProviderIsServiceKeyed --- .../src/ServiceLookup/CallSiteFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 72a5d508badde..48d2a22f5ed50 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -641,7 +641,7 @@ public void Add(ServiceIdentifier serviceIdentifier, ServiceCallSite serviceCall public bool IsService(Type serviceType) => IsService(new ServiceIdentifier(null, serviceType)); - public bool IsService(object key, Type serviceType) => IsService(new ServiceIdentifier(key, serviceType)); + public bool IsService(Type serviceType, object key) => IsService(new ServiceIdentifier(key, serviceType)); internal bool IsService(ServiceIdentifier serviceIdentifier) { From 24e1e72a36c526406b5b3288c3701c17875d61d7 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 15:07:24 +0200 Subject: [PATCH 18/43] Some nit fixes --- .../src/ServiceLookup/CallSiteFactory.cs | 6 +++--- .../src/ServiceLookup/ServiceDescriptorCacheKey.cs | 8 ++++---- .../tests/DI.Tests/KeyedServiceProviderContainerTests.cs | 1 - .../src/CompatibilitySuppressions.xml | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 48d2a22f5ed50..4b066dceb86d9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -315,7 +315,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica int slot = 0; for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (KeyEquals(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) + if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) { if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite) { @@ -325,7 +325,7 @@ private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamica } for (int i = _descriptors.Length - 1; i >= 0; i--) { - if (KeyEquals(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) + if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)) { if (TryCreateOpenGeneric(_descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite) { @@ -685,7 +685,7 @@ internal bool IsService(ServiceIdentifier serviceIdentifier) /// /// Returns true if both keys are null or equals, or if key1 is KeyedService.AnyKey and key2 is not null /// - private static bool KeyEquals(object? key1, object? key2) + private static bool KeysMatch(object? key1, object? key2) { if (key1 == null && key2 == null) return true; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs index 05e397b19cdb3..8b52653253495 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs @@ -48,12 +48,12 @@ public override bool Equals([NotNullWhen(true)] object? obj) public override int GetHashCode() { + if (ServiceKey == null) + { + return ServiceType.GetHashCode(); + } unchecked { - if (ServiceKey == null) - { - return ServiceType.GetHashCode(); - } return ((ServiceType?.GetHashCode() ?? 23) * 397) ^ ServiceKey.GetHashCode(); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs index 27dda2f2b4ffb..79322bb9ec419 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/KeyedServiceProviderContainerTests.cs @@ -8,7 +8,6 @@ namespace Microsoft.Extensions.DependencyInjection.Tests { - public class KeyedServiceProviderDefaultContainerTests : KeyedDependencyInjectionSpecificationTests { protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) => collection.BuildServiceProvider(ServiceProviderMode.Default); diff --git a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml b/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml index cae5310ec6d31..8969e45b4ad4b 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml @@ -1,5 +1,4 @@  - CP0004 From 8111510a2adaef5314677930a465dac2f1ff2b1a Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 15:09:25 +0200 Subject: [PATCH 19/43] Some nit fixes --- .../src/ISupportKeyedService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs index b013e7d45d43e..99fff38bd1626 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs @@ -30,7 +30,7 @@ public static class KeyedService { public static object AnyKey { get; } = new AnyKeyObj(); - private class AnyKeyObj + private sealed class AnyKeyObj { public override string? ToString() => "*"; } From b4eb5f2355b5ebf8515a8aae420d3a77d4354987 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 15:17:32 +0200 Subject: [PATCH 20/43] Cleanup CompatibilitySuppressions.xml --- .../src/CompatibilitySuppressions.xml | 38 +------------------ .../src/CompatibilitySuppressions.xml | 20 ---------- 2 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml index f3d1040ea4b55..a2b6aeed97520 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -7,12 +7,6 @@ ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -31,12 +25,6 @@ ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -55,12 +43,6 @@ ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -79,12 +61,6 @@ ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -103,12 +79,6 @@ ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -127,12 +97,6 @@ ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportRequiredKeyedService - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0001 T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions @@ -1423,4 +1387,4 @@ ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - \ No newline at end of file + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml deleted file mode 100644 index 0357fdc8d5e24..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.#ctor(System.DateTime,System.DateTime,System.TimeSpan,System.TimeSpan,System.DateTimeOffset,System.DateTimeOffset,System.Guid,System.Guid,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,System.Nullable{System.ConsoleColor},System.Nullable{System.ConsoleColor},System.Nullable{System.Int32},System.Nullable{System.Int32}) - true - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.ExplictServiceRegisterationWithIsService - true - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.TypeActivatorCreateInstanceUsesFirstMathchedConstructor(System.Object,System.String) - true - - \ No newline at end of file From 7cd437865fab3fd0ed5dcf17f250d5d719c2f835 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 16:04:09 +0200 Subject: [PATCH 21/43] WIP: ref fix tentative --- ...nsions.DependencyInjection.Abstractions.cs | 119 +- .../src/CompatibilitySuppressions.xml | 1385 +---------------- ...icrosoft.Extensions.DependencyInjection.cs | 4 +- 3 files changed, 21 insertions(+), 1487 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index ac76f0499015f..abb9b58cdbde2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -9,11 +9,11 @@ namespace Microsoft.Extensions.DependencyInjection public static partial class ActivatorUtilities { public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type instanceType, System.Type[] argumentTypes) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory(System.Type[] argumentTypes) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.Type[] argumentTypes) { throw null; } public static object CreateInstance(System.IServiceProvider provider, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type instanceType, params object[] parameters) { throw null; } - public static T CreateInstance(System.IServiceProvider provider, params object[] parameters) { throw null; } + public static T CreateInstance<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.IServiceProvider provider, params object[] parameters) { throw null; } public static object GetServiceOrCreateInstance(System.IServiceProvider provider, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type) { throw null; } - public static T GetServiceOrCreateInstance(System.IServiceProvider provider) { throw null; } + public static T GetServiceOrCreateInstance<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T>(System.IServiceProvider provider) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.All)] public partial class ActivatorUtilitiesConstructorAttribute : System.Attribute @@ -29,12 +29,6 @@ public ActivatorUtilitiesConstructorAttribute() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } } - [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] - public partial class FromKeyedServicesAttribute : System.Attribute - { - public FromKeyedServicesAttribute(object key) { } - public object Key { get { throw null; } } - } public partial interface IServiceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { } @@ -47,10 +41,6 @@ public partial interface IServiceProviderIsService { bool IsService(System.Type serviceType); } - public partial interface IServiceProviderIsServiceKeyed - { - bool IsService(System.Type serviceType, object serviceKey); - } public partial interface IServiceScope : System.IDisposable { System.IServiceProvider ServiceProvider { get; } @@ -59,19 +49,10 @@ public partial interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } - public partial interface ISupportKeyedService - { - object? GetKeyedService(System.Type serviceType, object serviceKey); - object GetRequiredKeyedService(System.Type serviceType, object serviceKey); - } public partial interface ISupportRequiredService { object GetRequiredService(System.Type serviceType); } - public static partial class KeyedService - { - public static object AnyKey { get { throw null; } } - } public delegate object ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public delegate T ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public partial class ServiceCollection : Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable @@ -92,134 +73,70 @@ public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.Add(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } - public static partial class ServiceCollectionKeyedServiceExtensions - { - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - } public static partial class ServiceCollectionServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object implementationInstance) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } } public partial class ServiceDescriptor { public ServiceDescriptor(System.Type serviceType, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object instance) { } - public ServiceDescriptor(System.Type serviceType, object? serviceKey, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } - public ServiceDescriptor(System.Type serviceType, object? serviceKey, object instance) { } - public ServiceDescriptor(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public System.Func? ImplementationFactory { get { throw null; } } public object? ImplementationInstance { get { throw null; } } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? ImplementationType { get { throw null; } } - public System.Func? KeyedImplementationFactory { get { throw null; } } public Microsoft.Extensions.DependencyInjection.ServiceLifetime Lifetime { get { throw null; } } - public object? ServiceKey { get { throw null; } } public System.Type ServiceType { get { throw null; } } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object serviceKey, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type serviceType, object implementationInstance) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Singleton(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } public override string ToString() { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } } - [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] - public partial class ServiceKeyAttribute : System.Attribute - { - public ServiceKeyAttribute() { } - } public enum ServiceLifetime { Singleton = 0, Scoped = 1, Transient = 2, } - public static partial class ServiceProviderKeyedServiceExtensions - { - [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("The native code for an IEnumerable might not be available at runtime.")] - public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } - public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, object serviceKey) { throw null; } - public static T? GetKeyedService(this System.IServiceProvider provider, object serviceKey) { throw null; } - public static object GetRequiredKeyedService(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } - public static T GetRequiredKeyedService(this System.IServiceProvider provider, object serviceKey) where T : notnull { throw null; } - } public static partial class ServiceProviderServiceExtensions { public static Microsoft.Extensions.DependencyInjection.AsyncServiceScope CreateAsyncScope(this Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) { throw null; } @@ -249,21 +166,21 @@ public static void TryAddEnumerable(this Microsoft.Extensions.DependencyInjectio public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } - public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, TService instance) where TService : class { } - public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service) { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, System.Func implementationFactory) { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } + public static void TryAddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } - public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } + public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml index a2b6aeed97520..accd3154e10d9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -1,1390 +1,9 @@  - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ISupportKeyedService - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.ServiceProviderKeyedServiceExtensions - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.#ctor(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object},Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.DescribeKeyed(System.Type,System.Object,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLifetime) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped(System.Type,System.Object,System.Type) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton(System.Type,System.Object,System.Type) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,``0) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedSingleton``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Func{System.IServiceProvider,System.Object}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient(System.Type,System.Object,System.Type) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``1(System.Object,System.Func{System.IServiceProvider,``0}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object,System.Func{System.IServiceProvider,``1}) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + M:Microsoft.Extensions.DependencyInjection.ObjectFactory.#ctor(System.Object,System.IntPtr) + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory``1(System.Type[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance``1(System.IServiceProvider,System.Object[])<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance``1(System.IServiceProvider)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionKeyedServiceExtensions.AddKeyedTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)<0>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient``2(Microsoft.Extensions.DependencyInjection.IServiceCollection)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedScoped``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.KeyedTransient``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2(System.Object)<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0016 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient``2<1>:[T:System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute] - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index c0982ef4f34e9..0b85156d60885 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -19,13 +19,11 @@ public static partial class ServiceCollectionContainerBuilderExtensions public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.DependencyInjection.ServiceProviderOptions options) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, bool validateScopes) { throw null; } } - public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInjection.ISupportKeyedService, System.IAsyncDisposable, System.IDisposable, System.IServiceProvider + public sealed partial class ServiceProvider : System.IAsyncDisposable, System.IDisposable, System.IServiceProvider { internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public object? GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } - public object GetRequiredKeyedService(System.Type serviceType, object serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions From c8e397cc408608f69ece95224aecd2ce17887e92 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 16:30:18 +0200 Subject: [PATCH 22/43] Fix ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs --- ...nsions.DependencyInjection.Abstractions.cs | 83 +++++++++++++++++++ .../src/ServiceDescriptor.cs | 2 +- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index abb9b58cdbde2..cf526d1a0f935 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -29,6 +29,12 @@ public ActivatorUtilitiesConstructorAttribute() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } } + [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] + public partial class FromKeyedServicesAttribute : System.Attribute + { + public FromKeyedServicesAttribute(object key) { } + public object Key { get { throw null; } } + } public partial interface IServiceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { } @@ -41,6 +47,10 @@ public partial interface IServiceProviderIsService { bool IsService(System.Type serviceType); } + public partial interface IServiceProviderIsServiceKeyed + { + bool IsService(System.Type serviceType, object serviceKey); + } public partial interface IServiceScope : System.IDisposable { System.IServiceProvider ServiceProvider { get; } @@ -49,10 +59,19 @@ public partial interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } + public partial interface ISupportKeyedService + { + object? GetKeyedService(System.Type serviceType, object serviceKey); + object GetRequiredKeyedService(System.Type serviceType, object serviceKey); + } public partial interface ISupportRequiredService { object GetRequiredService(System.Type serviceType); } + public static partial class KeyedService + { + public static object AnyKey { get { throw null; } } + } public delegate object ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public delegate T ObjectFactory(System.IServiceProvider serviceProvider, object?[]? arguments); public partial class ServiceCollection : Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable @@ -73,6 +92,32 @@ public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.Add(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } + public static partial class ServiceCollectionKeyedServiceExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + } public static partial class ServiceCollectionServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } @@ -103,15 +148,39 @@ public partial class ServiceDescriptor { public ServiceDescriptor(System.Type serviceType, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object instance) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, object instance) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public System.Func? ImplementationFactory { get { throw null; } } public object? ImplementationInstance { get { throw null; } } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? ImplementationType { get { throw null; } } + public System.Func? KeyedImplementationFactory { get { throw null; } } public Microsoft.Extensions.DependencyInjection.ServiceLifetime Lifetime { get { throw null; } } + public object? ServiceKey { get { throw null; } } public System.Type ServiceType { get { throw null; } } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object serviceKey, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class { throw null; } @@ -131,12 +200,26 @@ public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalys public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } } + [System.AttributeUsageAttribute(System.AttributeTargets.Parameter)] + public partial class ServiceKeyAttribute : System.Attribute + { + public ServiceKeyAttribute() { } + } public enum ServiceLifetime { Singleton = 0, Scoped = 1, Transient = 2, } + public static partial class ServiceProviderKeyedServiceExtensions + { + [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("The native code for an IEnumerable might not be available at runtime.")] + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, object serviceKey) { throw null; } + public static T? GetKeyedService(this System.IServiceProvider provider, object serviceKey) { throw null; } + public static object GetRequiredKeyedService(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } + public static T GetRequiredKeyedService(this System.IServiceProvider provider, object serviceKey) where T : notnull { throw null; } + } public static partial class ServiceProviderServiceExtensions { public static Microsoft.Extensions.DependencyInjection.AsyncServiceScope CreateAsyncScope(this Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index 178b04a53975b..0939274a516ee 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -591,7 +591,7 @@ public static ServiceDescriptor KeyedScoped(Type service, object serviceKey, Fun /// The type of the implementation. /// The of the service. /// A new instance of . - public static ServiceDescriptor Singleton( + public static ServiceDescriptor KeyedSingleton( object serviceKey) where TService : class where TImplementation : class, TService From 840d3af545ca6612c52a90bbb3e8fa5bbc03dc2a Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 16:32:02 +0200 Subject: [PATCH 23/43] Fix ref/Microsoft.Extensions.DependencyInjection.cs --- ...icrosoft.Extensions.DependencyInjection.cs | 4 +- .../src/CompatibilitySuppressions.xml | 109 +++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index 0b85156d60885..c0982ef4f34e9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -19,11 +19,13 @@ public static partial class ServiceCollectionContainerBuilderExtensions public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.DependencyInjection.ServiceProviderOptions options) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, bool validateScopes) { throw null; } } - public sealed partial class ServiceProvider : System.IAsyncDisposable, System.IDisposable, System.IServiceProvider + public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInjection.ISupportKeyedService, System.IAsyncDisposable, System.IDisposable, System.IServiceProvider { internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public object? GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } + public object GetRequiredKeyedService(System.Type serviceType, object serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml index 42539183a5a05..7cbfeefce99e3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml @@ -1,7 +1,114 @@  - + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.dll + lib/net462/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/net462/Microsoft.Extensions.DependencyInjection.dll + lib/net462/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/net6.0/Microsoft.Extensions.DependencyInjection.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/net8.0/Microsoft.Extensions.DependencyInjection.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/net462/Microsoft.Extensions.DependencyInjection.dll + lib/net462/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/net6.0/Microsoft.Extensions.DependencyInjection.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/net8.0/Microsoft.Extensions.DependencyInjection.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll + + + CP0008 + T:Microsoft.Extensions.DependencyInjection.ServiceProvider + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll + CP0014 M:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.DependencyInjection.ServiceProviderOptions):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] From 8ccac9e474eae402b80b2767b36309436e7702ee Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 21:12:27 +0200 Subject: [PATCH 24/43] Segregate keyed and non keyed ServiceDescriptor member, and throw when misuse is detected --- ...nsions.DependencyInjection.Abstractions.cs | 4 + .../src/CompatibilitySuppressions.xml | 75 ++++++- .../src/Resources/Strings.resx | 6 + .../src/ServiceDescriptor.cs | 191 ++++++++++++++---- .../src/DependencyInjectionEventSource.cs | 18 +- .../src/ServiceLookup/CallSiteFactory.cs | 25 +-- .../ServiceDescriptorExtensions.cs | 39 ++++ 7 files changed, 298 insertions(+), 60 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorExtensions.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index cf526d1a0f935..bfb55ed155142 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -156,7 +156,11 @@ public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalys public object? ImplementationInstance { get { throw null; } } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? ImplementationType { get { throw null; } } + public bool IsKeyedService { get { throw null; } } public System.Func? KeyedImplementationFactory { get { throw null; } } + public object? KeyedImplementationInstance { get { throw null; } } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] + public System.Type? KeyedImplementationType { get { throw null; } } public Microsoft.Extensions.DependencyInjection.ServiceLifetime Lifetime { get { throw null; } } public object? ServiceKey { get { throw null; } } public System.Type ServiceType { get { throw null; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml index accd3154e10d9..943b720f08059 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0002 @@ -6,4 +7,76 @@ lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx index 30021e2cc716d..d9eb294211515 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx @@ -170,4 +170,10 @@ This service provider doesn't support keyed services. + + This service descriptor is keyed. Your service provider may not support keyed services. + + + This service descriptor is not keyed. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index 0939274a516ee..25f0bbf79b8fa 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -44,7 +44,7 @@ public ServiceDescriptor( ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(implementationType); - ImplementationType = implementationType; + _implementationType = implementationType; } /// @@ -76,7 +76,7 @@ public ServiceDescriptor( ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(instance); - ImplementationInstance = instance; + _implementationInstance = instance; } /// @@ -94,7 +94,7 @@ public ServiceDescriptor( ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(factory); - ImplementationFactory = factory; + _implementationFactory = factory; } /// @@ -114,7 +114,7 @@ public ServiceDescriptor( ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(factory); - KeyedImplementationFactory = factory; + _implementationFactory = factory; } private ServiceDescriptor(Type serviceType, object? serviceKey, ServiceLifetime lifetime) @@ -139,80 +139,183 @@ private ServiceDescriptor(Type serviceType, object? serviceKey, ServiceLifetime /// public Type ServiceType { get; } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + private Type? _implementationType; + + /// + /// Gets the that implements the service. + /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + public Type? ImplementationType + { + get + { + if (IsKeyedService) + { + ThrowKeyedDescriptor(); + } + return _implementationType; + } + } + /// /// Gets the that implements the service. /// [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - public Type? ImplementationType { get; } + public Type? KeyedImplementationType + { + get + { + if (!IsKeyedService) + { + ThrowNonKeyedDescriptor(); + } + return _implementationType; + } + } + + private object? _implementationInstance; /// /// Gets the instance that implements the service. /// - public object? ImplementationInstance { get; } + public object? ImplementationInstance + { + get + { + if (IsKeyedService) + { + ThrowKeyedDescriptor(); + } + return _implementationInstance; + } + } + + /// + /// Gets the instance that implements the service. + /// + public object? KeyedImplementationInstance + { + get + { + if (!IsKeyedService) + { + ThrowNonKeyedDescriptor(); + } + return _implementationInstance; + } + } + + private object? _implementationFactory; /// /// Gets the factory used for creating service instances. /// - public Func? ImplementationFactory { get; } + public Func? ImplementationFactory + { + get + { + if (IsKeyedService) + { + ThrowKeyedDescriptor(); + } + return (Func?) _implementationFactory; + } + } /// /// Gets the factory used for creating Keyed service instances. /// - public Func? KeyedImplementationFactory { get; } + public Func? KeyedImplementationFactory + { + get + { + if (!IsKeyedService) + { + ThrowNonKeyedDescriptor(); + } + return (Func?) _implementationFactory; + } + } + + public bool IsKeyedService => ServiceKey != null; /// public override string ToString() { string? lifetime = $"{nameof(ServiceType)}: {ServiceType} {nameof(Lifetime)}: {Lifetime} "; - if (ServiceKey != null) + if (IsKeyedService) { lifetime += $"{nameof(ServiceKey)}: {ServiceKey} "; - } - if (ImplementationType != null) - { - return lifetime + $"{nameof(ImplementationType)}: {ImplementationType}"; - } + if (KeyedImplementationType != null) + { + return lifetime + $"{nameof(KeyedImplementationType)}: {KeyedImplementationType}"; + } - if (ImplementationFactory != null) - { - return lifetime + $"{nameof(ImplementationFactory)}: {ImplementationFactory.Method}"; - } + if (KeyedImplementationFactory != null) + { + return lifetime + $"{nameof(KeyedImplementationFactory)}: {KeyedImplementationFactory.Method}"; + } - if (KeyedImplementationFactory != null) - { - return lifetime + $"{nameof(KeyedImplementationFactory)}: {KeyedImplementationFactory.Method}"; + return lifetime + $"{nameof(KeyedImplementationInstance)}: {KeyedImplementationInstance}"; } + else + { + if (ImplementationType != null) + { + return lifetime + $"{nameof(ImplementationType)}: {ImplementationType}"; + } - return lifetime + $"{nameof(ImplementationInstance)}: {ImplementationInstance}"; + if (ImplementationFactory != null) + { + return lifetime + $"{nameof(ImplementationFactory)}: {ImplementationFactory.Method}"; + } + + return lifetime + $"{nameof(ImplementationInstance)}: {ImplementationInstance}"; + } } internal Type GetImplementationType() { - if (ImplementationType != null) - { - return ImplementationType; - } - else if (ImplementationInstance != null) + if (ServiceKey == null) { - return ImplementationInstance.GetType(); + if (ImplementationType != null) + { + return ImplementationType; + } + else if (ImplementationInstance != null) + { + return ImplementationInstance.GetType(); + } + else if (ImplementationFactory != null) + { + Type[]? typeArguments = ImplementationFactory.GetType().GenericTypeArguments; + + Debug.Assert(typeArguments.Length == 2); + + return typeArguments[1]; + } } - else if (ImplementationFactory != null) - { - Type[]? typeArguments = ImplementationFactory.GetType().GenericTypeArguments; - - Debug.Assert(typeArguments.Length == 2); - - return typeArguments[1]; - } - else if (KeyedImplementationFactory != null) + else { - Type[]? typeArguments = KeyedImplementationFactory.GetType().GenericTypeArguments; - - Debug.Assert(typeArguments.Length == 3); - - return typeArguments[2]; + if (KeyedImplementationType != null) + { + return KeyedImplementationType; + } + else if (KeyedImplementationInstance != null) + { + return KeyedImplementationInstance.GetType(); + } + else if (KeyedImplementationFactory != null) + { + Type[]? typeArguments = KeyedImplementationFactory.GetType().GenericTypeArguments; + + Debug.Assert(typeArguments.Length == 2); + + return typeArguments[1]; + } } Debug.Assert(false, "ImplementationType, ImplementationInstance, ImplementationFactory or KeyedImplementationFactory must be non null"); @@ -923,5 +1026,9 @@ private string DebuggerToString() return debugText; } + + private static void ThrowKeyedDescriptor() => throw new InvalidOperationException(SR.KeyedDescriptorMisuse); + + private static void ThrowNonKeyedDescriptor() => throw new InvalidOperationException(SR.NonKeyedDescriptorMisuse); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index b12dff0b495dd..c258be1dedcac 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Linq.Expressions; @@ -243,20 +244,27 @@ private static void AppendServiceDescriptor(StringBuilder builder, ServiceDescri builder.Append(descriptor.Lifetime); builder.Append("\", "); - if (descriptor.ImplementationType is not null) + if (descriptor.HasImplementationType()) { builder.Append("\"implementationType\": \""); - builder.Append(descriptor.ImplementationType); + builder.Append(descriptor.GetImplementationType()); } - else if (descriptor.ImplementationFactory is not null) + else if (!descriptor.IsKeyedService && descriptor.ImplementationFactory != null) { builder.Append("\"implementationFactory\": \""); builder.Append(descriptor.ImplementationFactory.Method); } - else if (descriptor.ImplementationInstance is not null) + else if (descriptor.IsKeyedService && descriptor.KeyedImplementationFactory != null) { + builder.Append("\"implementationFactory\": \""); + builder.Append(descriptor.KeyedImplementationFactory.Method); + } + else if (descriptor.HasImplementationInstance()) + { + object? instance = descriptor.GetImplementationInstance(); + Debug.Assert(instance != null, "descriptor.ImplementationInstance != null"); builder.Append("\"implementationInstance\": \""); - builder.Append(descriptor.ImplementationInstance.GetType()); + builder.Append(instance.GetType()); builder.Append(" (instance)"); } else diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 4b066dceb86d9..a2f7309bb2ff4 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -39,7 +39,7 @@ private void Populate() Type serviceType = descriptor.ServiceType; if (serviceType.IsGenericTypeDefinition) { - Type? implementationType = descriptor.ImplementationType; + Type? implementationType = descriptor.GetImplementationType(); if (implementationType == null || !implementationType.IsGenericTypeDefinition) { @@ -67,10 +67,10 @@ private void Populate() ValidateTrimmingAnnotations(serviceType, serviceTypeGenericArguments, implementationType, implementationTypeGenericArguments); } } - else if (descriptor.ImplementationInstance == null && descriptor.ImplementationFactory == null && descriptor.KeyedImplementationFactory == null) + else if (!descriptor.HasImplementationInstance() && !descriptor.HasImplementationFactory()) { - Debug.Assert(descriptor.ImplementationType != null); - Type implementationType = descriptor.ImplementationType; + Type? implementationType = descriptor.GetImplementationType(); + Debug.Assert(implementationType != null); if (implementationType.IsGenericTypeDefinition || implementationType.IsAbstract || @@ -377,21 +377,21 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult ServiceCallSite callSite; var lifetime = new ResultCache(descriptor.Lifetime, serviceIdentifier, slot); - if (descriptor.ImplementationInstance != null) + if (descriptor.HasImplementationInstance()) { - callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance); + callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.GetImplementationInstance()); } - else if (descriptor.ImplementationFactory != null) + else if (!descriptor.IsKeyedService && descriptor.ImplementationFactory != null) { callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } - else if (descriptor.KeyedImplementationFactory != null) + else if (descriptor.IsKeyedService && descriptor.KeyedImplementationFactory != null) { callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, serviceIdentifier.ServiceKey!, descriptor.KeyedImplementationFactory); } - else if (descriptor.ImplementationType != null) + else if (descriptor.HasImplementationType()) { - callSite = CreateConstructorCallSite(lifetime, serviceIdentifier, descriptor.ImplementationType, callSiteChain); + callSite = CreateConstructorCallSite(lifetime, serviceIdentifier, descriptor.GetImplementationType()!, callSiteChain); } else { @@ -423,7 +423,8 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult return serviceCallSite; } - Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); + Type? implementationType = descriptor.GetImplementationType(); + Debug.Assert(implementationType != null, "descriptor.ImplementationType != null"); var lifetime = new ResultCache(descriptor.Lifetime, serviceIdentifier, slot); Type closedType; try @@ -434,7 +435,7 @@ private static CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResult VerifyOpenGenericAotCompatibility(serviceIdentifier.ServiceType, genericTypeArguments); } - closedType = descriptor.ImplementationType.MakeGenericType(genericTypeArguments); + closedType = implementationType.MakeGenericType(genericTypeArguments); } catch (ArgumentException) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorExtensions.cs new file mode 100644 index 0000000000000..33454344e5680 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorExtensions.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.DependencyInjection.ServiceLookup +{ + internal static class ServiceDescriptorExtensions + { + public static bool HasImplementationInstance(this ServiceDescriptor serviceDescriptor) => GetImplementationInstance(serviceDescriptor) != null; + + public static bool HasImplementationFactory(this ServiceDescriptor serviceDescriptor) => GetImplementationFactory(serviceDescriptor) != null; + + public static bool HasImplementationType(this ServiceDescriptor serviceDescriptor) => GetImplementationType(serviceDescriptor) != null; + + public static object? GetImplementationInstance(this ServiceDescriptor serviceDescriptor) + { + return serviceDescriptor.IsKeyedService + ? serviceDescriptor.KeyedImplementationInstance + : serviceDescriptor.ImplementationInstance; + } + + public static object? GetImplementationFactory(this ServiceDescriptor serviceDescriptor) + { + return serviceDescriptor.IsKeyedService + ? serviceDescriptor.KeyedImplementationFactory + : serviceDescriptor.ImplementationFactory; + } + + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + public static Type? GetImplementationType(this ServiceDescriptor serviceDescriptor) + { + return serviceDescriptor.IsKeyedService + ? serviceDescriptor.KeyedImplementationType + : serviceDescriptor.ImplementationType; + } + } +} From 2558c99555e2f923b45c6b997bb1e967911d4243 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Fri, 23 Jun 2023 21:30:25 +0200 Subject: [PATCH 25/43] Enforce that the type of the parameter marked with the ServiceKey attribute matches the type of the key used for lookup. --- ...edDependencyInjectionSpecificationTests.cs | 21 +++++++++++++++++++ .../src/Resources/Strings.resx | 3 +++ .../src/ServiceLookup/CallSiteFactory.cs | 7 ++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 897c08af57cec..0b836d3541e56 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -5,6 +5,7 @@ using Xunit; using Microsoft.Extensions.DependencyInjection.Specification.Fakes; using System.Linq; +using System.Security.Cryptography; namespace Microsoft.Extensions.DependencyInjection.Specification { @@ -205,6 +206,19 @@ public void ResolveKeyedServiceSingletonFactoryWithAnyKey() } } + [Fact] + public void ResolveKeyedServiceSingletonFactoryWithAnyKeyIgnoreWrongType() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedTransient(KeyedService.AnyKey); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + Assert.NotNull(provider.GetKeyedService(87)); + Assert.ThrowsAny(() => provider.GetKeyedService(new object())); + } + [Fact] public void ResolveKeyedServiceSingletonType() { @@ -288,5 +302,12 @@ public OtherService( public IService Service2 { get; } } + + internal class ServiceWithIntKey : IService + { + private readonly int _id; + + public ServiceWithIntKey([ServiceKey] int id) => _id = id; + } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx index ee997b2c5bdb9..e6f57dcbb5a1e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx @@ -189,4 +189,7 @@ No service for type '{0}' has been registered. + + The type of the key used for lookup doesn't match the type in the constructor parameter with the ServiceKey attribute. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index a2f7309bb2ff4..deb2d31daf561 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -577,8 +577,13 @@ private ConstructorCallSite CreateConstructorCallSite( { foreach (var attribute in parameters[index].GetCustomAttributes(true)) { - if (attribute is ServiceKeyAttribute) + if (serviceIdentifier.ServiceKey != null && attribute is ServiceKeyAttribute) { + // Check if the parameter type matches + if (parameterType != serviceIdentifier.ServiceKey.GetType()) + { + throw new InvalidOperationException(SR.InvalidServiceKeyType); + } callSite = new ConstantCallSite(parameterType, serviceIdentifier.ServiceKey); break; } From aea27cb9fe6575cf0c363b112b0515379142d086 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 26 Jun 2023 13:27:38 +0200 Subject: [PATCH 26/43] Add TryAddKeyed* extensions --- ...nsions.DependencyInjection.Abstractions.cs | 25 ++ .../src/CompatibilitySuppressions.xml | 36 ++ ...viceCollectionKeyedDescriptorExtensions.cs | 416 ++++++++++++++++++ 3 files changed, 477 insertions(+) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index bfb55ed155142..971e7edd4e5f0 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -270,4 +270,29 @@ public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } } + + public static partial class ServiceCollectionKeyedDescriptorExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type serviceType, object serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) { throw null; } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey, TService instance) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } + } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml index 943b720f08059..590b9a36e0715 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -1,6 +1,42 @@  + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + CP0001 + T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions + ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll + CP0002 M:Microsoft.Extensions.DependencyInjection.ObjectFactory.#ctor(System.Object,System.IntPtr) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs new file mode 100644 index 0000000000000..6ecf6f9405405 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs @@ -0,0 +1,416 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.DependencyInjection.Extensions +{ + /// + /// Extension methods for adding and removing services to an . + /// + public static class ServiceCollectionKeyedDescriptorExtensions + { + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + public static void TryAddKeyedTransient( + this IServiceCollection collection, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, + object serviceKey) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + + var descriptor = ServiceDescriptor.KeyedTransient(service, serviceKey, service); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// with the implementation + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The implementation type of the service. + public static void TryAddKeyedTransient( + this IServiceCollection collection, + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationType); + + var descriptor = ServiceDescriptor.KeyedTransient(service, serviceKey, implementationType); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The factory that creates the service. + public static void TryAddKeyedTransient( + this IServiceCollection collection, + Type service, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationFactory); + + var descriptor = ServiceDescriptor.KeyedTransient(service, serviceKey, implementationFactory); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + public static void TryAddKeyedTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedTransient(collection, typeof(TService), serviceKey, typeof(TService)); + } + + /// + /// Adds the specified as a service + /// implementation type specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The . + /// The service key. + public static void TryAddKeyedTransient(this IServiceCollection collection, object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedTransient(collection, typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + /// The factory that creates the service. + public static void TryAddKeyedTransient( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + services.TryAdd(ServiceDescriptor.KeyedTransient(serviceKey, implementationFactory)); + } + + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + public static void TryAddKeyedScoped( + this IServiceCollection collection, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, + object serviceKey) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + + var descriptor = ServiceDescriptor.KeyedScoped(service, serviceKey, service); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// with the implementation + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The implementation type of the service. + public static void TryAddKeyedScoped( + this IServiceCollection collection, + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationType); + + var descriptor = ServiceDescriptor.KeyedScoped(service, serviceKey, implementationType); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The factory that creates the service. + public static void TryAddKeyedScoped( + this IServiceCollection collection, + Type service, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationFactory); + + var descriptor = ServiceDescriptor.KeyedScoped(service, serviceKey, implementationFactory); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + public static void TryAddKeyedScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedScoped(collection, typeof(TService), serviceKey, typeof(TService)); + } + + /// + /// Adds the specified as a service + /// implementation type specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The . + /// The service key. + public static void TryAddKeyedScoped(this IServiceCollection collection, object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedScoped(collection, typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The factory that creates the service. + /// The service key. + public static void TryAddKeyedScoped( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + services.TryAdd(ServiceDescriptor.KeyedScoped(serviceKey, implementationFactory)); + } + + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + public static void TryAddKeyedSingleton( + this IServiceCollection collection, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, + object serviceKey) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + + var descriptor = ServiceDescriptor.KeyedSingleton(service, serviceKey, service); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// with the implementation + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The implementation type of the service. + public static void TryAddKeyedSingleton( + this IServiceCollection collection, + Type service, + object serviceKey, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationType); + + var descriptor = ServiceDescriptor.KeyedSingleton(service, serviceKey, implementationType); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The . + /// The type of the service to register. + /// The service key. + /// The factory that creates the service. + public static void TryAddKeyedSingleton( + this IServiceCollection collection, + Type service, + object serviceKey, + Func implementationFactory) + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(service); + ThrowHelper.ThrowIfNull(implementationFactory); + + var descriptor = ServiceDescriptor.KeyedSingleton(service, serviceKey, implementationFactory); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + public static void TryAddKeyedSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + where TService : class + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedSingleton(collection, typeof(TService), serviceKey, typeof(TService)); + } + + /// + /// Adds the specified as a service + /// implementation type specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The type of the implementation to use. + /// The . + /// The service key. + public static void TryAddKeyedSingleton(this IServiceCollection collection, object serviceKey) + where TService : class + where TImplementation : class, TService + { + ThrowHelper.ThrowIfNull(collection); + + TryAddKeyedSingleton(collection, typeof(TService), serviceKey, typeof(TImplementation)); + } + + /// + /// Adds the specified as a service + /// with an instance specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + /// The instance of the service to add. + public static void TryAddKeyedSingleton(this IServiceCollection collection, object serviceKey, TService instance) + where TService : class + { + ThrowHelper.ThrowIfNull(collection); + ThrowHelper.ThrowIfNull(instance); + + var descriptor = ServiceDescriptor.KeyedSingleton(serviceType: typeof(TService), serviceKey, implementationInstance: instance); + ServiceCollectionDescriptorExtensions.TryAdd(collection, descriptor); + } + + /// + /// Adds the specified as a service + /// using the factory specified in + /// to the if the service type hasn't already been registered. + /// + /// The type of the service to add. + /// The . + /// The service key. + /// The factory that creates the service. + public static void TryAddKeyedSingleton( + this IServiceCollection services, + object serviceKey, + Func implementationFactory) + where TService : class + { + services.TryAdd(ServiceDescriptor.KeyedSingleton(serviceKey, implementationFactory)); + } + + /// + /// Removes all services of type in . + /// + /// The . + /// The service key. + /// The for chaining. + public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, object serviceKey) + { + return RemoveAllKeyed(collection, typeof(T), serviceKey); + } + + /// + /// Removes all services of type in . + /// + /// The . + /// The service type to remove. + /// The service key. + /// The for chaining. + public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, Type serviceType, object serviceKey) + { + ThrowHelper.ThrowIfNull(serviceType); + + for (int i = collection.Count - 1; i >= 0; i--) + { + ServiceDescriptor? descriptor = collection[i]; + if (descriptor.ServiceType == serviceType && descriptor.ServiceKey == serviceKey) + { + collection.RemoveAt(i); + } + } + + return collection; + } + } +} From afeaed1ed361cdb45e17405dad21a7a864523cd4 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 26 Jun 2023 16:38:13 +0200 Subject: [PATCH 27/43] Fixes and added tests --- ...nsions.DependencyInjection.Abstractions.cs | 2 +- ...ServiceCollectionKeyedServiceExtensions.cs | 2 +- .../src/ServiceDescriptor.cs | 4 +- ...iceCollectionKeyedServiceExtensionsTest.cs | 434 ++++++++++++++++++ 4 files changed, 438 insertions(+), 4 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 971e7edd4e5f0..fb88031632c44 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -109,7 +109,7 @@ public static partial class ServiceCollectionKeyedServiceExtensions public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, TService implementationInstance) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs index 8eddf3c4513f6..92d1f61e734ad 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs @@ -476,7 +476,7 @@ public static IServiceCollection AddKeyedSingleton( public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, object serviceKey, - Func implementationFactory) + Func implementationFactory) where TService : class where TImplementation : class, TService { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index 25f0bbf79b8fa..6d0c4bd4ad4fa 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -312,9 +312,9 @@ internal Type GetImplementationType() { Type[]? typeArguments = KeyedImplementationFactory.GetType().GenericTypeArguments; - Debug.Assert(typeArguments.Length == 2); + Debug.Assert(typeArguments.Length == 3); - return typeArguments[1]; + return typeArguments[2]; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs new file mode 100644 index 0000000000000..9338dc292c582 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs @@ -0,0 +1,434 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.DependencyInjection.Specification.Fakes; +using Microsoft.Extensions.DependencyInjection.Tests; +using Xunit; + +namespace Microsoft.Extensions.DependencyInjection +{ + public class ServiceCollectionKeyedServiceExtensionsTest + { + private static readonly FakeService _instance = new FakeService(); + + public static TheoryData AddImplementationTypeData + { + get + { + var serviceType = typeof(IFakeService); + var implementationType = typeof(FakeService); + return new TheoryData, Type, object, Type, ServiceLifetime> + { + { collection => collection.AddKeyedTransient(serviceType, "some-key-1", implementationType), serviceType, "some-key-1", implementationType, ServiceLifetime.Transient }, + { collection => collection.AddKeyedTransient("some-key-2"), serviceType, "some-key-2", implementationType, ServiceLifetime.Transient }, + { collection => collection.AddKeyedTransient("some-key-3"), serviceType, "some-key-3", serviceType, ServiceLifetime.Transient }, + { collection => collection.AddKeyedTransient(implementationType, "some-key-4"), implementationType, "some-key-4", implementationType, ServiceLifetime.Transient }, + + { collection => collection.AddKeyedScoped(serviceType, "some-key-5", implementationType), serviceType, "some-key-5", implementationType, ServiceLifetime.Scoped }, + { collection => collection.AddKeyedScoped("some-key-6"), serviceType, "some-key-6", implementationType, ServiceLifetime.Scoped }, + { collection => collection.AddKeyedScoped("some-key-7"), serviceType, "some-key-7", serviceType, ServiceLifetime.Scoped }, + { collection => collection.AddKeyedScoped(implementationType, "some-key-8"), implementationType, "some-key-8", implementationType, ServiceLifetime.Scoped }, + + { collection => collection.AddKeyedSingleton(serviceType, "some-key-9", implementationType), serviceType, "some-key-9", implementationType, ServiceLifetime.Singleton }, + { collection => collection.AddKeyedSingleton("some-key-10"), serviceType, "some-key-10", implementationType, ServiceLifetime.Singleton }, + { collection => collection.AddKeyedSingleton("some-key-12"), serviceType, "some-key-12", serviceType, ServiceLifetime.Singleton }, + { collection => collection.AddKeyedSingleton(serviceType: implementationType, "some-key-13"), implementationType, "some-key-13", implementationType, ServiceLifetime.Singleton }, + }; + } + } + + [Theory] + [MemberData(nameof(AddImplementationTypeData))] + public void AddWithTypeAddsServiceWithRightLifecyle(Action addTypeAction, + Type expectedServiceType, + object expectedKey, + Type expectedImplementationType, + ServiceLifetime lifeCycle) + { + // Arrange + var collection = new ServiceCollection(); + + // Act + addTypeAction(collection); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(expectedServiceType, descriptor.ServiceType); + Assert.Equal(expectedKey, descriptor.ServiceKey); + Assert.Equal(expectedImplementationType, descriptor.KeyedImplementationType); + Assert.Equal(lifeCycle, descriptor.Lifetime); + } + + public static TheoryData AddImplementationFactoryData + { + get + { + var serviceType = typeof(IFakeService); + var implementationType = typeof(FakeService); + var objectType = typeof(object); + + return new TheoryData, Type, object, Type, ServiceLifetime> + { + { collection => collection.AddKeyedTransient(serviceType, "some-key-1", (s,k) => new FakeService()), serviceType, "some-key-1", objectType, ServiceLifetime.Transient }, + { collection => collection.AddKeyedTransient("some-key-2", (s,k) => new FakeService()), serviceType, "some-key-2", serviceType, ServiceLifetime.Transient }, + { collection => collection.AddKeyedTransient("some-key-3", (s,k) => new FakeService()), serviceType, "some-key-3", implementationType, ServiceLifetime.Transient }, + + { collection => collection.AddKeyedScoped(serviceType, "some-key-4", (s,k) => new FakeService()), serviceType, "some-key-4", objectType, ServiceLifetime.Scoped }, + { collection => collection.AddKeyedScoped("some-key-5", (s,k) => new FakeService()), serviceType, "some-key-5", serviceType, ServiceLifetime.Scoped }, + { collection => collection.AddKeyedScoped("some-key-6", (s,k) => new FakeService()), serviceType, "some-key-6", implementationType, ServiceLifetime.Scoped }, + + { collection => collection.AddKeyedSingleton(serviceType, "some-key-7", (s,k) => new FakeService()), serviceType, "some-key-7", objectType, ServiceLifetime.Singleton }, + { collection => collection.AddKeyedSingleton("some-key-8", (s,k) => new FakeService()), serviceType, "some-key-8", serviceType, ServiceLifetime.Singleton }, + { collection => collection.AddKeyedSingleton("some-key-9", (s,k) => new FakeService()), serviceType, "some-key-9", implementationType, ServiceLifetime.Singleton }, + }; + } + } + + [Theory] + [MemberData(nameof(AddImplementationFactoryData))] + public void AddWithFactoryAddsServiceWithRightLifecyle( + Action addAction, + Type serviceType, + object serviceKey, + Type implementationType, + ServiceLifetime lifeCycle) + { + // Arrange + var collection = new ServiceCollection(); + + // Act + addAction(collection); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(serviceType, descriptor.ServiceType); + Assert.Equal(serviceKey, descriptor.ServiceKey); + Assert.Equal(implementationType, descriptor.GetImplementationType()); + Assert.Equal(lifeCycle, descriptor.Lifetime); + } + + public static TheoryData AddSingletonData + { + get + { + return new TheoryData> + { + { collection => collection.AddKeyedSingleton("service", _instance) }, + { collection => collection.AddKeyedSingleton(typeof(IFakeService), "service", _instance) }, + }; + } + } + + [Theory] + [MemberData(nameof(AddSingletonData))] + public void AddSingleton_AddsWithSingletonLifecycle(Action addAction) + { + // Arrange + var collection = new ServiceCollection(); + + // Act + addAction(collection); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(typeof(IFakeService), descriptor.ServiceType); + Assert.Equal("service", descriptor.ServiceKey.ToString()); + Assert.Same(_instance, descriptor.KeyedImplementationInstance); + Assert.Equal(ServiceLifetime.Singleton, descriptor.Lifetime); + } + + [Theory] + [MemberData(nameof(AddSingletonData))] + public void TryAddNoOpFailsIfExists(Action addAction) + { + // Arrange + var collection = new ServiceCollection(); + addAction(collection); + var d = ServiceDescriptor.KeyedTransient("service"); + + // Act + collection.TryAdd(d); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(typeof(IFakeService), descriptor.ServiceType); + Assert.Same(_instance, descriptor.KeyedImplementationInstance); + Assert.Equal(ServiceLifetime.Singleton, descriptor.Lifetime); + } + + public static TheoryData TryAddImplementationTypeData + { + get + { + var serviceType = typeof(IFakeService); + var implementationType = typeof(FakeService); + return new TheoryData, Type, object, Type, ServiceLifetime> + { + { collection => collection.TryAddKeyedTransient(serviceType, "key-1", implementationType), serviceType, "key-1", implementationType, ServiceLifetime.Transient }, + { collection => collection.TryAddKeyedTransient("key-2"), serviceType, "key-2", implementationType, ServiceLifetime.Transient }, + { collection => collection.TryAddKeyedTransient("key-3"), serviceType, "key-3", serviceType, ServiceLifetime.Transient }, + { collection => collection.TryAddKeyedTransient(implementationType, "key-4"), implementationType, "key-4", implementationType, ServiceLifetime.Transient }, + + { collection => collection.TryAddKeyedScoped(serviceType, "key-1", implementationType), serviceType, "key-1", implementationType, ServiceLifetime.Scoped }, + { collection => collection.TryAddKeyedScoped("key-2"), serviceType, "key-2", implementationType, ServiceLifetime.Scoped }, + { collection => collection.TryAddKeyedScoped("key-3"), serviceType, "key-3", serviceType, ServiceLifetime.Scoped }, + { collection => collection.TryAddKeyedScoped(implementationType, "key-4"), implementationType, "key-4", implementationType, ServiceLifetime.Scoped }, + + { collection => collection.TryAddKeyedSingleton(serviceType, "key-5", implementationType), serviceType, "key-5", implementationType, ServiceLifetime.Singleton }, + { collection => collection.TryAddKeyedSingleton("key-6"), serviceType, "key-6", implementationType, ServiceLifetime.Singleton }, + { collection => collection.TryAddKeyedSingleton("key-7"), serviceType, "key-7", serviceType, ServiceLifetime.Singleton }, + { collection => collection.TryAddKeyedSingleton(service: implementationType, "key-8"), implementationType, "key-8", implementationType, ServiceLifetime.Singleton }, + }; + } + } + + [Theory] + [MemberData(nameof(TryAddImplementationTypeData))] + public void TryAdd_WithType_AddsService( + Action addAction, + Type expectedServiceType, + object expectedServiceKey, + Type expectedImplementationType, + ServiceLifetime expectedLifetime) + { + // Arrange + var collection = new ServiceCollection(); + + // Act + addAction(collection); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(expectedServiceType, descriptor.ServiceType); + Assert.Equal(expectedServiceKey, descriptor.ServiceKey); + Assert.Same(expectedImplementationType, descriptor.KeyedImplementationType); + Assert.Equal(expectedLifetime, descriptor.Lifetime); + } + + [Theory] + [MemberData(nameof(TryAddImplementationTypeData))] + public void TryAdd_WithType_DoesNotAddDuplicate( + Action addAction, + Type expectedServiceType, + object expectedServiceKey, + // Test verifies that descriptor is not added so we don't need to assert it's properties +#pragma warning disable xUnit1026 + Type expectedImplementationType, + ServiceLifetime expectedLifetime +#pragma warning restore xUnit1026 + ) + { + // Arrange + var collection = new ServiceCollection + { + ServiceDescriptor.KeyedTransient(expectedServiceType, expectedServiceKey, expectedServiceType) + }; + + // Act + addAction(collection); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(expectedServiceType, descriptor.ServiceType); + Assert.Same(expectedServiceType, descriptor.KeyedImplementationType); + Assert.Equal(ServiceLifetime.Transient, descriptor.Lifetime); + } + + [Fact] + public void TryAddIfMissingActuallyAdds() + { + // Arrange + var collection = new ServiceCollection(); + var key = new object(); + var d = ServiceDescriptor.KeyedTransient(key); + + // Act + collection.TryAdd(d); + + // Assert + var descriptor = Assert.Single(collection); + Assert.Equal(typeof(IFakeService), descriptor.ServiceType); + Assert.Equal(key, descriptor.ServiceKey); + Assert.Null(descriptor.KeyedImplementationInstance); + Assert.Equal(ServiceLifetime.Transient, descriptor.Lifetime); + } + + public static TheoryData TryAddEnumerableImplementationTypeData + { + get + { + var serviceType = typeof(IFakeService); + var implementationType = typeof(FakeService); + return new TheoryData + { + { ServiceDescriptor.KeyedTransient("service1"), serviceType, "service1", implementationType, ServiceLifetime.Transient }, + { ServiceDescriptor.KeyedTransient("service2", (s,k) => new FakeService()), serviceType, "service2", implementationType, ServiceLifetime.Transient }, + + { ServiceDescriptor.KeyedScoped("service3"), serviceType, "service3", implementationType, ServiceLifetime.Scoped }, + { ServiceDescriptor.KeyedScoped("service4", (s,k) => new FakeService()), serviceType, "service4", implementationType, ServiceLifetime.Scoped }, + + { ServiceDescriptor.KeyedSingleton("service5"), serviceType, "service5", implementationType, ServiceLifetime.Singleton }, + { ServiceDescriptor.KeyedSingleton("service6", (s,k) => new FakeService()), serviceType, "service6", implementationType, ServiceLifetime.Singleton }, + + { ServiceDescriptor.KeyedSingleton("service6", _instance), serviceType, "service6", implementationType, ServiceLifetime.Singleton }, + }; + } + } + + [Theory] + [MemberData(nameof(TryAddEnumerableImplementationTypeData))] + public void TryAddEnumerable_AddsService( + ServiceDescriptor descriptor, + Type expectedServiceType, + object expectedKey, + Type expectedImplementationType, + ServiceLifetime expectedLifetime) + { + // Arrange + var collection = new ServiceCollection(); + + // Act + collection.TryAddEnumerable(descriptor); + + // Assert + var d = Assert.Single(collection); + Assert.Equal(expectedServiceType, d.ServiceType); + Assert.Equal(expectedKey, d.ServiceKey); + Assert.Equal(expectedImplementationType, d.GetImplementationType()); + Assert.Equal(expectedLifetime, d.Lifetime); + } + + + [Theory] + [MemberData(nameof(TryAddEnumerableImplementationTypeData))] + public void TryAddEnumerable_DoesNotAddDuplicate( + ServiceDescriptor descriptor, + Type expectedServiceType, + object expectedKey, + Type expectedImplementationType, + ServiceLifetime expectedLifetime) + { + // Arrange + var collection = new ServiceCollection(); + collection.TryAddEnumerable(descriptor); + + // Act + collection.TryAddEnumerable(descriptor); + + // Assert + var d = Assert.Single(collection); + Assert.Equal(expectedServiceType, d.ServiceType); + Assert.Equal(expectedKey, d.ServiceKey); + Assert.Equal(expectedImplementationType, d.GetImplementationType()); + Assert.Equal(expectedLifetime, d.Lifetime); + } + + public static TheoryData TryAddEnumerableInvalidImplementationTypeData + { + get + { + var serviceType = typeof(IFakeService); + var key = new object(); + var implementationType = typeof(FakeService); + var objectType = typeof(object); + + return new TheoryData + { + { ServiceDescriptor.KeyedTransient(key, (s,k) => new FakeService()), serviceType, serviceType }, + { ServiceDescriptor.KeyedTransient(serviceType, key, (s,k) => new FakeService()), serviceType, objectType }, + + { ServiceDescriptor.KeyedScoped(key, (s,k) => new FakeService()), serviceType, serviceType }, + { ServiceDescriptor.KeyedScoped(serviceType, key, (s,k) => new FakeService()), serviceType, objectType }, + + { ServiceDescriptor.KeyedSingleton(key, (s,k) => new FakeService()), serviceType, serviceType }, + { ServiceDescriptor.KeyedSingleton(serviceType, key, (s,k) => new FakeService()), serviceType, objectType }, + }; + } + } + + [Theory] + [MemberData(nameof(TryAddEnumerableInvalidImplementationTypeData))] + public void TryAddEnumerable_ThrowsWhenAddingIndistinguishableImplementationType( + ServiceDescriptor descriptor, + Type serviceType, + Type implementationType) + { + // Arrange + var collection = new ServiceCollection(); + + AssertExtensions.ThrowsContains(() => collection.TryAddEnumerable(descriptor), + string.Format(@"Implementation type cannot be '{0}' because it is indistinguishable from other services registered for '{1}'.", implementationType, serviceType)); + } + + [Fact] + public void AddSequence_AddsServicesToCollection() + { + // Arrange + var collection = new ServiceCollection(); + var descriptor1 = new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient); + var descriptor2 = new ServiceDescriptor(typeof(IFakeOuterService), "key1", typeof(FakeOuterService), ServiceLifetime.Transient); + var descriptors = new[] { descriptor1, descriptor2 }; + + // Act + var result = collection.Add(descriptors); + + // Assert + Assert.Equal(descriptors, collection); + } + + [Fact] + public void Replace_AddsServiceIfServiceTypeIsNotRegistered() + { + // Arrange + var collection = new ServiceCollection(); + var descriptor1 = new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient); + var descriptor2 = new ServiceDescriptor(typeof(IFakeOuterService), "key1", typeof(FakeOuterService), ServiceLifetime.Transient); + collection.Add(descriptor1); + + // Act + collection.Replace(descriptor2); + + // Assert + Assert.Equal(new[] { descriptor1, descriptor2 }, collection); + } + + [Fact] + public void Replace_ReplacesFirstServiceWithMatchingServiceType() + { + // Arrange + var collection = new ServiceCollection(); + var descriptor1 = new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient); + var descriptor2 = new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient); + collection.Add(descriptor1); + collection.Add(descriptor2); + var descriptor3 = new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Singleton); + + // Act + collection.Replace(descriptor3); + + // Assert + Assert.Equal(new[] { descriptor2, descriptor3 }, collection); + } + + [Fact] + public void RemoveAll_RemovesAllServicesWithMatchingServiceType() + { + // Arrange + var descriptor = new ServiceDescriptor(typeof(IFakeServiceInstance), "key1", typeof(FakeService), ServiceLifetime.Transient); + var collection = new ServiceCollection + { + descriptor, + new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient), + new ServiceDescriptor(typeof(IFakeService), "key1", typeof(FakeService), ServiceLifetime.Transient) + }; + + // Act + collection.RemoveAllKeyed("key1"); + + // Assert + Assert.Equal(new[] { descriptor }, collection); + } + } +} From f2beeb2bfb7b4c4641a589214ab51151050c4854 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 28 Jun 2023 10:12:09 +0200 Subject: [PATCH 28/43] Rename ISupportKeyedService to IKeyedServiceProvider and make it implement IServiceProvider --- .../Microsoft.Extensions.DependencyInjection.Abstractions.cs | 4 +++- .../src/{ISupportKeyedService.cs => IKeyedServiceProvider.cs} | 2 +- .../src/ServiceProviderKeyedServiceExtensions.cs | 4 ++-- .../ref/Microsoft.Extensions.DependencyInjection.cs | 2 +- .../src/ServiceProvider.cs | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) rename src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/{ISupportKeyedService.cs => IKeyedServiceProvider.cs} (96%) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index fb88031632c44..5fdf6dca18165 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System; + namespace Microsoft.Extensions.DependencyInjection { public static partial class ActivatorUtilities @@ -59,7 +61,7 @@ public partial interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } - public partial interface ISupportKeyedService + public partial interface IKeyedServiceProvider : IServiceProvider { object? GetKeyedService(System.Type serviceType, object serviceKey); object GetRequiredKeyedService(System.Type serviceType, object serviceKey); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs similarity index 96% rename from src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs rename to src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs index 99fff38bd1626..024606502df28 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ISupportKeyedService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs @@ -5,7 +5,7 @@ namespace Microsoft.Extensions.DependencyInjection { - public interface ISupportKeyedService + public interface IKeyedServiceProvider : IServiceProvider { /// /// Gets the service object of the specified type. diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs index f4f013ffbe7b7..bba215b993469 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs @@ -23,7 +23,7 @@ public static class ServiceProviderKeyedServiceExtensions { ThrowHelper.ThrowIfNull(provider); - if (provider is ISupportKeyedService keyedServiceProvider) + if (provider is IKeyedServiceProvider keyedServiceProvider) { return (T?)keyedServiceProvider.GetKeyedService(typeof(T), serviceKey); } @@ -44,7 +44,7 @@ public static object GetRequiredKeyedService(this IServiceProvider provider, Typ ThrowHelper.ThrowIfNull(provider); ThrowHelper.ThrowIfNull(serviceType); - if (provider is ISupportKeyedService requiredServiceSupportingProvider) + if (provider is IKeyedServiceProvider requiredServiceSupportingProvider) { return requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index c0982ef4f34e9..0151304a51b3d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -19,7 +19,7 @@ public static partial class ServiceCollectionContainerBuilderExtensions public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.DependencyInjection.ServiceProviderOptions options) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, bool validateScopes) { throw null; } } - public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInjection.ISupportKeyedService, System.IAsyncDisposable, System.IDisposable, System.IServiceProvider + public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInjection.IKeyedServiceProvider, System.IAsyncDisposable, System.IDisposable, System.IServiceProvider { internal ServiceProvider() { } public void Dispose() { } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index aa3985064ec02..c0bce4a8e48f4 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -17,7 +17,7 @@ namespace Microsoft.Extensions.DependencyInjection /// [DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerTypeProxy(typeof(ServiceProviderDebugView))] - public sealed class ServiceProvider : IServiceProvider, ISupportKeyedService, IDisposable, IAsyncDisposable + public sealed class ServiceProvider : IServiceProvider, IKeyedServiceProvider, IDisposable, IAsyncDisposable { private readonly CallSiteValidator? _callSiteValidator; From 115c3ef99848a6a8449e36d5f7340682a2462aaf Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 28 Jun 2023 10:16:58 +0200 Subject: [PATCH 29/43] Rename IServiceProviderIsServiceKeyed to IKeyedServiceProviderIsService and rename its method IsService to IsKeyedService --- .../Microsoft.Extensions.DependencyInjection.Abstractions.cs | 4 ++-- .../src/IServiceProviderIsService.cs | 4 ++-- .../src/ServiceLookup/CallSiteFactory.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 5fdf6dca18165..b73ab8804e608 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -49,9 +49,9 @@ public partial interface IServiceProviderIsService { bool IsService(System.Type serviceType); } - public partial interface IServiceProviderIsServiceKeyed + public partial interface IKeyedServiceProviderIsService { - bool IsService(System.Type serviceType, object serviceKey); + bool IsKeyedService(System.Type serviceType, object serviceKey); } public partial interface IServiceScope : System.IDisposable { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs index 954295ca3d6aa..40e188ab8a027 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs @@ -18,7 +18,7 @@ public interface IServiceProviderIsService bool IsService(Type serviceType); } - public interface IServiceProviderIsServiceKeyed + public interface IKeyedServiceProviderIsService { /// /// Determines if the specified service type is available from the . @@ -26,6 +26,6 @@ public interface IServiceProviderIsServiceKeyed /// An object that specifies the type of service object to test. /// The of the service. /// true if the specified service is a available, false if it is not. - bool IsService(Type serviceType, object serviceKey); + bool IsKeyedService(Type serviceType, object serviceKey); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index deb2d31daf561..002a70560c4b2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteFactory : IServiceProviderIsService, IServiceProviderIsServiceKeyed + internal sealed class CallSiteFactory : IServiceProviderIsService, IKeyedServiceProviderIsService { private const int DefaultSlot = 0; private readonly ServiceDescriptor[] _descriptors; @@ -647,7 +647,7 @@ public void Add(ServiceIdentifier serviceIdentifier, ServiceCallSite serviceCall public bool IsService(Type serviceType) => IsService(new ServiceIdentifier(null, serviceType)); - public bool IsService(Type serviceType, object key) => IsService(new ServiceIdentifier(key, serviceType)); + public bool IsKeyedService(Type serviceType, object key) => IsService(new ServiceIdentifier(key, serviceType)); internal bool IsService(ServiceIdentifier serviceIdentifier) { From 840d2854cf6637500cacf2b2fffc987da2e64e2a Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 28 Jun 2023 10:26:26 +0200 Subject: [PATCH 30/43] Merge extension methods from ServiceCollectionKeyedDescriptorExtensions to ServiceCollectionDescriptorExtensions --- ...nsions.DependencyInjection.Abstractions.cs | 4 -- .../src/CompatibilitySuppressions.xml | 38 +------------------ .../ServiceCollectionDescriptorExtensions.cs | 2 +- ...viceCollectionKeyedDescriptorExtensions.cs | 2 +- 4 files changed, 3 insertions(+), 43 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index b73ab8804e608..fce2570fdcb8b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -271,10 +271,6 @@ public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection public static void TryAddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } - } - - public static partial class ServiceCollectionKeyedDescriptorExtensions - { public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type serviceType, object serviceKey) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) { throw null; } public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml index 590b9a36e0715..2199b993a9836 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml @@ -1,42 +1,6 @@  - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0001 - T:Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionKeyedDescriptorExtensions - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - CP0002 M:Microsoft.Extensions.DependencyInjection.ObjectFactory.#ctor(System.Object,System.IntPtr) @@ -115,4 +79,4 @@ ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - \ No newline at end of file + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs index f2bee7f56c472..f2435dca6cfce 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.DependencyInjection.Extensions /// /// Extension methods for adding and removing services to an . /// - public static class ServiceCollectionDescriptorExtensions + public static partial class ServiceCollectionDescriptorExtensions { /// /// Adds the specified to the . diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs index 6ecf6f9405405..d34f6c4f643fc 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.DependencyInjection.Extensions /// /// Extension methods for adding and removing services to an . /// - public static class ServiceCollectionKeyedDescriptorExtensions + public static partial class ServiceCollectionDescriptorExtensions { /// /// Adds the specified as a service From 8f4e6f3ba47f83c5a5a712ccb5f3bf37cf297c4c Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 28 Jun 2023 10:29:06 +0200 Subject: [PATCH 31/43] Merge extension methods from ServiceCollectionKeyedServiceExtensions to ServiceCollectionServiceExtensions --- .../Microsoft.Extensions.DependencyInjection.Abstractions.cs | 5 +---- .../src/ServiceCollectionKeyedServiceExtensions.cs | 2 +- .../src/ServiceCollectionServiceExtensions.cs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index fce2570fdcb8b..922d4508aae8c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -94,7 +94,7 @@ public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.Add(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } - public static partial class ServiceCollectionKeyedServiceExtensions + public static partial class ServiceCollectionServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } @@ -119,9 +119,6 @@ public static partial class ServiceCollectionKeyedServiceExtensions public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - } - public static partial class ServiceCollectionServiceExtensions - { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs index 92d1f61e734ad..9de15681dd68d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Extension methods for adding services to an . /// - public static class ServiceCollectionKeyedServiceExtensions + public static partial class ServiceCollectionServiceExtensions { /// /// Adds a transient service of the type specified in with an diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs index c07bde152cffc..15427514a23f7 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Extension methods for adding services to an . /// - public static class ServiceCollectionServiceExtensions + public static partial class ServiceCollectionServiceExtensions { /// /// Adds a transient service of the type specified in with an From 845d9147b8b7546afac382d959f61ab3deab5339 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 28 Jun 2023 10:35:09 +0200 Subject: [PATCH 32/43] Restore wrongfully removed CompatibilitySuppressions.xml --- .../src/CompatibilitySuppressions.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml new file mode 100644 index 0000000000000..c4c68039b773f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml @@ -0,0 +1,10 @@ + + + + + + CP0002 + M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.TypeActivatorCreateInstanceUsesFirstMathchedConstructor(System.Object,System.String) + true + + \ No newline at end of file From a5705dc848cd04be23b82523d2fd076441bda415 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 15:09:13 +0200 Subject: [PATCH 33/43] Files renaming --- ...tensions.cs => ServiceCollectionDescriptorExtensions.Keyed.cs} | 0 ...eExtensions.cs => ServiceCollectionServiceExtensions.Keyed.cs} | 0 .../{ServiceDescriptorCacheKey.cs => ServiceIdentifier.cs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/{ServiceCollectionKeyedDescriptorExtensions.cs => ServiceCollectionDescriptorExtensions.Keyed.cs} (100%) rename src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/{ServiceCollectionKeyedServiceExtensions.cs => ServiceCollectionServiceExtensions.Keyed.cs} (100%) rename src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/{ServiceDescriptorCacheKey.cs => ServiceIdentifier.cs} (100%) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs similarity index 100% rename from src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionKeyedDescriptorExtensions.cs rename to src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs similarity index 100% rename from src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionKeyedServiceExtensions.cs rename to src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceIdentifier.cs similarity index 100% rename from src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceDescriptorCacheKey.cs rename to src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceIdentifier.cs From 460ecb4c969cb05ea87a0f66bfbaaef77d92c41d Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 17:55:44 +0200 Subject: [PATCH 34/43] Make serviceKey nullable where possible --- ...nsions.DependencyInjection.Abstractions.cs | 140 +++++++++--------- ...iceCollectionDescriptorExtensions.Keyed.cs | 30 ++-- .../src/IKeyedServiceProvider.cs | 4 +- .../src/IServiceProviderIsService.cs | 2 +- ...erviceCollectionServiceExtensions.Keyed.cs | 30 ++-- .../src/ServiceDescriptor.cs | 19 +-- .../ServiceProviderKeyedServiceExtensions.cs | 10 +- ...edDependencyInjectionSpecificationTests.cs | 32 ++++ ...icrosoft.Extensions.DependencyInjection.cs | 4 +- .../src/ServiceLookup/CallSiteFactory.cs | 2 +- .../src/ServiceProvider.cs | 4 +- ...iceCollectionKeyedServiceExtensionsTest.cs | 2 +- 12 files changed, 156 insertions(+), 123 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 922d4508aae8c..95bef4db0df68 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -51,7 +51,7 @@ public partial interface IServiceProviderIsService } public partial interface IKeyedServiceProviderIsService { - bool IsKeyedService(System.Type serviceType, object serviceKey); + bool IsKeyedService(System.Type serviceType, object? serviceKey); } public partial interface IServiceScope : System.IDisposable { @@ -63,8 +63,8 @@ public partial interface IServiceScopeFactory } public partial interface IKeyedServiceProvider : IServiceProvider { - object? GetKeyedService(System.Type serviceType, object serviceKey); - object GetRequiredKeyedService(System.Type serviceType, object serviceKey); + object? GetKeyedService(System.Type serviceType, object? serviceKey); + object GetRequiredKeyedService(System.Type serviceType, object? serviceKey); } public partial interface ISupportRequiredService { @@ -96,29 +96,29 @@ public void RemoveAt(int index) { } } public static partial class ServiceCollectionServiceExtensions { - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object? serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object? serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType, object? serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type serviceType) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } @@ -165,25 +165,25 @@ public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalys public System.Type ServiceType { get { throw null; } } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object serviceKey, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object? serviceKey, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor DescribeKeyed(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object serviceKey, object implementationInstance) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, TService implementationInstance) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, System.Func implementationFactory) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey) where TService : class where TImplementation : class, TService { throw null; } - public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedScoped(object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type serviceType, object? serviceKey, object implementationInstance) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object? serviceKey, TService implementationInstance) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedSingleton(object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object? serviceKey, System.Func implementationFactory) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object? serviceKey, System.Func implementationFactory) where TService : class { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object? serviceKey) where TService : class where TImplementation : class, TService { throw null; } + public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor KeyedTransient(object? serviceKey, System.Func implementationFactory) where TService : class where TImplementation : class, TService { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, System.Func implementationFactory) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Type service, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { throw null; } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Scoped(System.Func implementationFactory) where TService : class { throw null; } @@ -217,11 +217,11 @@ public enum ServiceLifetime public static partial class ServiceProviderKeyedServiceExtensions { [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("The native code for an IEnumerable might not be available at runtime.")] - public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } - public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, object serviceKey) { throw null; } - public static T? GetKeyedService(this System.IServiceProvider provider, object serviceKey) { throw null; } - public static object GetRequiredKeyedService(this System.IServiceProvider provider, System.Type serviceType, object serviceKey) { throw null; } - public static T GetRequiredKeyedService(this System.IServiceProvider provider, object serviceKey) where T : notnull { throw null; } + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, System.Type serviceType, object? serviceKey) { throw null; } + public static System.Collections.Generic.IEnumerable GetKeyedServices(this System.IServiceProvider provider, object? serviceKey) { throw null; } + public static T? GetKeyedService(this System.IServiceProvider provider, object? serviceKey) { throw null; } + public static object GetRequiredKeyedService(this System.IServiceProvider provider, System.Type serviceType, object? serviceKey) { throw null; } + public static T GetRequiredKeyedService(this System.IServiceProvider provider, object? serviceKey) where T : notnull { throw null; } } public static partial class ServiceProviderServiceExtensions { @@ -268,26 +268,26 @@ public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection public static void TryAddTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class { } public static void TryAddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection) where TService : class where TImplementation : class, TService { } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type serviceType, object serviceKey) { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) { throw null; } - public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } - public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } - public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } - public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } - public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey, TService instance) where TService : class { } - public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } - public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object serviceKey) { } - public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, System.Func implementationFactory) { } - public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } - public static void TryAddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class { } - public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object serviceKey, System.Func implementationFactory) where TService : class { } - public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object serviceKey) where TService : class where TImplementation : class, TService { } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type serviceType, object? serviceKey) { throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection RemoveAllKeyed(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) { throw null; } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object? serviceKey) { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedScoped<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object? serviceKey) { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedSingleton<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey, TService instance) where TService : class { } + public static void TryAddKeyedSingleton(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type service, object? serviceKey) { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, System.Func implementationFactory) { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Type service, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType) { } + public static void TryAddKeyedTransient<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object? serviceKey, System.Func implementationFactory) where TService : class { } + public static void TryAddKeyedTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs index d34f6c4f643fc..4a4a6f92675d9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs @@ -22,7 +22,7 @@ public static partial class ServiceCollectionDescriptorExtensions public static void TryAddKeyedTransient( this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -43,7 +43,7 @@ public static void TryAddKeyedTransient( public static void TryAddKeyedTransient( this IServiceCollection collection, Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(collection); @@ -84,7 +84,7 @@ public static void TryAddKeyedTransient( /// The type of the service to add. /// The . /// The service key. - public static void TryAddKeyedTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(collection); @@ -101,7 +101,7 @@ public static void TryAddKeyedTransient( /// The type of the implementation to use. /// The . /// The service key. - public static void TryAddKeyedTransient(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedTransient(this IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { @@ -138,7 +138,7 @@ public static void TryAddKeyedTransient( public static void TryAddKeyedScoped( this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -159,7 +159,7 @@ public static void TryAddKeyedScoped( public static void TryAddKeyedScoped( this IServiceCollection collection, Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(collection); @@ -200,7 +200,7 @@ public static void TryAddKeyedScoped( /// The type of the service to add. /// The . /// The service key. - public static void TryAddKeyedScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(collection); @@ -217,7 +217,7 @@ public static void TryAddKeyedScoped( /// The type of the implementation to use. /// The . /// The service key. - public static void TryAddKeyedScoped(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedScoped(this IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { @@ -254,7 +254,7 @@ public static void TryAddKeyedScoped( public static void TryAddKeyedSingleton( this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -275,7 +275,7 @@ public static void TryAddKeyedSingleton( public static void TryAddKeyedSingleton( this IServiceCollection collection, Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(collection); @@ -316,7 +316,7 @@ public static void TryAddKeyedSingleton( /// The type of the service to add. /// The . /// The service key. - public static void TryAddKeyedSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection, object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(collection); @@ -333,7 +333,7 @@ public static void TryAddKeyedSingleton( /// The type of the implementation to use. /// The . /// The service key. - public static void TryAddKeyedSingleton(this IServiceCollection collection, object serviceKey) + public static void TryAddKeyedSingleton(this IServiceCollection collection, object? serviceKey) where TService : class where TImplementation : class, TService { @@ -351,7 +351,7 @@ public static void TryAddKeyedSingleton( /// The . /// The service key. /// The instance of the service to add. - public static void TryAddKeyedSingleton(this IServiceCollection collection, object serviceKey, TService instance) + public static void TryAddKeyedSingleton(this IServiceCollection collection, object? serviceKey, TService instance) where TService : class { ThrowHelper.ThrowIfNull(collection); @@ -385,7 +385,7 @@ public static void TryAddKeyedSingleton( /// The . /// The service key. /// The for chaining. - public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, object serviceKey) + public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, object? serviceKey) { return RemoveAllKeyed(collection, typeof(T), serviceKey); } @@ -397,7 +397,7 @@ public static IServiceCollection RemoveAllKeyed(this IServiceCollection colle /// The service type to remove. /// The service key. /// The for chaining. - public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, Type serviceType, object serviceKey) + public static IServiceCollection RemoveAllKeyed(this IServiceCollection collection, Type serviceType, object? serviceKey) { ThrowHelper.ThrowIfNull(serviceType); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs index 024606502df28..ff6814eace2e0 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs @@ -13,7 +13,7 @@ public interface IKeyedServiceProvider : IServiceProvider /// An object that specifies the type of service object to get. /// An object that specifies the key of service object to get. /// A service object of type serviceType. -or- null if there is no service object of type serviceType. - object? GetKeyedService(Type serviceType, object serviceKey); + object? GetKeyedService(Type serviceType, object? serviceKey); /// /// Gets service of type from the implementing @@ -23,7 +23,7 @@ public interface IKeyedServiceProvider : IServiceProvider /// The of the service. /// A service object of type . /// Throws an exception if the cannot create the object. - object GetRequiredKeyedService(Type serviceType, object serviceKey); + object GetRequiredKeyedService(Type serviceType, object? serviceKey); } public static class KeyedService diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs index 40e188ab8a027..1d747085c4579 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs @@ -26,6 +26,6 @@ public interface IKeyedServiceProviderIsService /// An object that specifies the type of service object to test. /// The of the service. /// true if the specified service is a available, false if it is not. - bool IsKeyedService(Type serviceType, object serviceKey); + bool IsKeyedService(Type serviceType, object? serviceKey); } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs index 9de15681dd68d..edec7feb8cfef 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs @@ -25,7 +25,7 @@ public static partial class ServiceCollectionServiceExtensions public static IServiceCollection AddKeyedTransient( this IServiceCollection services, Type serviceType, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(services); @@ -72,7 +72,7 @@ public static IServiceCollection AddKeyedTransient( /// public static IServiceCollection AddKeyedTransient( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class where TImplementation : class, TService { @@ -93,7 +93,7 @@ public static IServiceCollection AddKeyedTransient( public static IServiceCollection AddKeyedTransient( this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -112,7 +112,7 @@ public static IServiceCollection AddKeyedTransient( /// public static IServiceCollection AddKeyedTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -183,7 +183,7 @@ public static IServiceCollection AddKeyedTransient( public static IServiceCollection AddKeyedScoped( this IServiceCollection services, Type serviceType, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(services); @@ -230,7 +230,7 @@ public static IServiceCollection AddKeyedScoped( /// public static IServiceCollection AddKeyedScoped( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class where TImplementation : class, TService { @@ -251,7 +251,7 @@ public static IServiceCollection AddKeyedScoped( public static IServiceCollection AddKeyedScoped( this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -270,7 +270,7 @@ public static IServiceCollection AddKeyedScoped( /// public static IServiceCollection AddKeyedScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -342,7 +342,7 @@ public static IServiceCollection AddKeyedScoped( public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, Type serviceType, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(services); @@ -389,7 +389,7 @@ public static IServiceCollection AddKeyedSingleton( /// public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class where TImplementation : class, TService { @@ -410,7 +410,7 @@ public static IServiceCollection AddKeyedSingleton( public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, - object serviceKey) + object? serviceKey) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -429,7 +429,7 @@ public static IServiceCollection AddKeyedSingleton( /// public static IServiceCollection AddKeyedSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>( this IServiceCollection services, - object serviceKey) + object? serviceKey) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -500,7 +500,7 @@ public static IServiceCollection AddKeyedSingleton( public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, Type serviceType, - object serviceKey, + object? serviceKey, object implementationInstance) { ThrowHelper.ThrowIfNull(services); @@ -524,7 +524,7 @@ public static IServiceCollection AddKeyedSingleton( /// public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, - object serviceKey, + object? serviceKey, TService implementationInstance) where TService : class { @@ -537,7 +537,7 @@ public static IServiceCollection AddKeyedSingleton( private static IServiceCollection AddKeyed( IServiceCollection collection, Type serviceType, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index 6d0c4bd4ad4fa..d8856f0e832ec 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -106,12 +106,13 @@ public ServiceDescriptor( /// The of the service. public ServiceDescriptor( Type serviceType, - object? serviceKey, + object serviceKey, Func factory, ServiceLifetime lifetime) : this(serviceType, serviceKey, lifetime) { ThrowHelper.ThrowIfNull(serviceType); + ThrowHelper.ThrowIfNull(serviceKey); ThrowHelper.ThrowIfNull(factory); _implementationFactory = factory; @@ -346,7 +347,7 @@ internal Type GetImplementationType() /// The type of the implementation. /// The of the service. /// A new instance of . - public static ServiceDescriptor KeyedTransient(object serviceKey) + public static ServiceDescriptor KeyedTransient(object? serviceKey) where TService : class where TImplementation : class, TService { @@ -382,7 +383,7 @@ public static ServiceDescriptor Transient( /// A new instance of . public static ServiceDescriptor KeyedTransient( Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(service); @@ -523,7 +524,7 @@ public static ServiceDescriptor KeyedTransient(Type service, object serviceKey, /// The type of the implementation. /// The of the service. /// A new instance of . - public static ServiceDescriptor KeyedScoped(object serviceKey) + public static ServiceDescriptor KeyedScoped(object? serviceKey) where TService : class where TImplementation : class, TService { @@ -556,7 +557,7 @@ public static ServiceDescriptor Scoped( /// A new instance of . public static ServiceDescriptor KeyedScoped( Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { return DescribeKeyed(service, serviceKey, implementationType, ServiceLifetime.Scoped); @@ -695,7 +696,7 @@ public static ServiceDescriptor KeyedScoped(Type service, object serviceKey, Fun /// The of the service. /// A new instance of . public static ServiceDescriptor KeyedSingleton( - object serviceKey) + object? serviceKey) where TService : class where TImplementation : class, TService { @@ -731,7 +732,7 @@ public static ServiceDescriptor Singleton( /// A new instance of . public static ServiceDescriptor KeyedSingleton( Type service, - object serviceKey, + object? serviceKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { ThrowHelper.ThrowIfNull(service); @@ -881,7 +882,7 @@ public static ServiceDescriptor Singleton(TService implementationInsta /// The instance of the implementation. /// A new instance of . public static ServiceDescriptor KeyedSingleton( - object serviceKey, + object? serviceKey, TService implementationInstance) where TService : class { @@ -919,7 +920,7 @@ public static ServiceDescriptor Singleton( /// A new instance of . public static ServiceDescriptor KeyedSingleton( Type serviceType, - object serviceKey, + object? serviceKey, object implementationInstance) { ThrowHelper.ThrowIfNull(serviceType); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs index bba215b993469..4ae52a0e9ed49 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderKeyedServiceExtensions.cs @@ -19,7 +19,7 @@ public static class ServiceProviderKeyedServiceExtensions /// The to retrieve the service object from. /// An object that specifies the key of service object to get. /// A service object of type or null if there is no such service. - public static T? GetKeyedService(this IServiceProvider provider, object serviceKey) + public static T? GetKeyedService(this IServiceProvider provider, object? serviceKey) { ThrowHelper.ThrowIfNull(provider); @@ -39,7 +39,7 @@ public static class ServiceProviderKeyedServiceExtensions /// An object that specifies the key of service object to get. /// A service object of type . /// There is no service of type . - public static object GetRequiredKeyedService(this IServiceProvider provider, Type serviceType, object serviceKey) + public static object GetRequiredKeyedService(this IServiceProvider provider, Type serviceType, object? serviceKey) { ThrowHelper.ThrowIfNull(provider); ThrowHelper.ThrowIfNull(serviceType); @@ -60,7 +60,7 @@ public static object GetRequiredKeyedService(this IServiceProvider provider, Typ /// An object that specifies the key of service object to get. /// A service object of type . /// There is no service of type . - public static T GetRequiredKeyedService(this IServiceProvider provider, object serviceKey) where T : notnull + public static T GetRequiredKeyedService(this IServiceProvider provider, object? serviceKey) where T : notnull { ThrowHelper.ThrowIfNull(provider); @@ -74,7 +74,7 @@ public static T GetRequiredKeyedService(this IServiceProvider provider, objec /// The to retrieve the services from. /// An object that specifies the key of service object to get. /// An enumeration of services of type . - public static IEnumerable GetKeyedServices(this IServiceProvider provider, object serviceKey) + public static IEnumerable GetKeyedServices(this IServiceProvider provider, object? serviceKey) { ThrowHelper.ThrowIfNull(provider); @@ -89,7 +89,7 @@ public static IEnumerable GetKeyedServices(this IServiceProvider provider, /// An object that specifies the key of service object to get. /// An enumeration of services of type . [RequiresDynamicCode("The native code for an IEnumerable might not be available at runtime.")] - public static IEnumerable GetKeyedServices(this IServiceProvider provider, Type serviceType, object serviceKey) + public static IEnumerable GetKeyedServices(this IServiceProvider provider, Type serviceType, object? serviceKey) { ThrowHelper.ThrowIfNull(provider); ThrowHelper.ThrowIfNull(serviceType); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 0b836d3541e56..41de033994f40 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -29,6 +29,38 @@ public void ResolveKeyedService() Assert.Same(service2, provider.GetKeyedService("service2")); } + [Fact] + public void ResolveNullKeyedService() + { + var service1 = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddKeyedSingleton(null, service1); + + var provider = CreateServiceProvider(serviceCollection); + + var nonKeyed = provider.GetServices(); + var nullKey = provider.GetKeyedService(null); + + Assert.Same(service1, nonKeyed); + Assert.Same(service1, nullKey); + } + + [Fact] + public void ResolveNonKeyedService() + { + var service1 = new Service(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(service1); + + var provider = CreateServiceProvider(serviceCollection); + + var nonKeyed = provider.GetServices(); + var nullKey = provider.GetKeyedService(null); + + Assert.Same(service1, nonKeyed); + Assert.Same(service1, nullKey); + } + [Fact] public void ResolveKeyedOpenGenericService() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs index 0151304a51b3d..8c7be14b68312 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/ref/Microsoft.Extensions.DependencyInjection.cs @@ -24,8 +24,8 @@ public sealed partial class ServiceProvider : Microsoft.Extensions.DependencyInj internal ServiceProvider() { } public void Dispose() { } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public object? GetKeyedService(System.Type serviceType, object serviceKey) { throw null; } - public object GetRequiredKeyedService(System.Type serviceType, object serviceKey) { throw null; } + public object? GetKeyedService(System.Type serviceType, object? serviceKey) { throw null; } + public object GetRequiredKeyedService(System.Type serviceType, object? serviceKey) { throw null; } public object? GetService(System.Type serviceType) { throw null; } } public partial class ServiceProviderOptions diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 002a70560c4b2..495490bc9ff84 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -647,7 +647,7 @@ public void Add(ServiceIdentifier serviceIdentifier, ServiceCallSite serviceCall public bool IsService(Type serviceType) => IsService(new ServiceIdentifier(null, serviceType)); - public bool IsKeyedService(Type serviceType, object key) => IsService(new ServiceIdentifier(key, serviceType)); + public bool IsKeyedService(Type serviceType, object? key) => IsService(new ServiceIdentifier(key, serviceType)); internal bool IsService(ServiceIdentifier serviceIdentifier) { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index c0bce4a8e48f4..dc523a38c57f2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -96,10 +96,10 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// The service that was produced. public object? GetService(Type serviceType) => GetService(ServiceIdentifier.FromServiceType(serviceType), Root); - public object? GetKeyedService(Type serviceType, object serviceKey) + public object? GetKeyedService(Type serviceType, object? serviceKey) => GetService(new ServiceIdentifier(serviceKey, serviceType), Root); - public object GetRequiredKeyedService(Type serviceType, object serviceKey) + public object GetRequiredKeyedService(Type serviceType, object? serviceKey) { object? service = GetKeyedService(serviceType, serviceKey); if (service == null) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs index 9338dc292c582..e3f7110b2c296 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs @@ -91,7 +91,7 @@ public static TheoryData AddImplementationFactoryData public void AddWithFactoryAddsServiceWithRightLifecyle( Action addAction, Type serviceType, - object serviceKey, + object? serviceKey, Type implementationType, ServiceLifetime lifeCycle) { From 72b2b5d963c4d59453680591abc7b276ecc7fd73 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 18:43:42 +0200 Subject: [PATCH 35/43] IServiceProviderIsKeyedService --- ...nsions.DependencyInjection.Abstractions.cs | 2 +- .../src/IServiceProviderIsKeyedService.cs | 18 +++ .../src/IServiceProviderIsService.cs | 11 -- ...edDependencyInjectionSpecificationTests.cs | 4 +- ...roviderIsKeyedServiceSpecificationTests.cs | 129 ++++++++++++++++++ .../src/ServiceLookup/CallSiteFactory.cs | 5 +- .../src/ServiceProvider.cs | 1 + 7 files changed, 154 insertions(+), 16 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsKeyedService.cs create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 95bef4db0df68..d3695a9f7711e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -49,7 +49,7 @@ public partial interface IServiceProviderIsService { bool IsService(System.Type serviceType); } - public partial interface IKeyedServiceProviderIsService + public partial interface IServiceProviderIsKeyedService : IServiceProviderIsService { bool IsKeyedService(System.Type serviceType, object? serviceKey); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsKeyedService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsKeyedService.cs new file mode 100644 index 0000000000000..39cda6b1ebcfc --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsKeyedService.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + public interface IServiceProviderIsKeyedService : IServiceProviderIsService + { + /// + /// Determines if the specified service type is available from the . + /// + /// An object that specifies the type of service object to test. + /// The of the service. + /// true if the specified service is a available, false if it is not. + bool IsKeyedService(Type serviceType, object? serviceKey); + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs index 1d747085c4579..b24ab154d16e9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderIsService.cs @@ -17,15 +17,4 @@ public interface IServiceProviderIsService /// true if the specified service is a available, false if it is not. bool IsService(Type serviceType); } - - public interface IKeyedServiceProviderIsService - { - /// - /// Determines if the specified service type is available from the . - /// - /// An object that specifies the type of service object to test. - /// The of the service. - /// true if the specified service is a available, false if it is not. - bool IsKeyedService(Type serviceType, object? serviceKey); - } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 41de033994f40..7dec0df829278 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -38,7 +38,7 @@ public void ResolveNullKeyedService() var provider = CreateServiceProvider(serviceCollection); - var nonKeyed = provider.GetServices(); + var nonKeyed = provider.GetService(); var nullKey = provider.GetKeyedService(null); Assert.Same(service1, nonKeyed); @@ -54,7 +54,7 @@ public void ResolveNonKeyedService() var provider = CreateServiceProvider(serviceCollection); - var nonKeyed = provider.GetServices(); + var nonKeyed = provider.GetService(); var nullKey = provider.GetKeyedService(null); Assert.Same(service1, nonKeyed); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs new file mode 100644 index 0000000000000..c7a9fa469ae28 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection.Specification.Fakes; +using Xunit; + +namespace Microsoft.Extensions.DependencyInjection.Specification +{ + public abstract partial class KeyedDependencyInjectionSpecificationTests + { + public virtual bool SupportsIServiceProviderIsKeyedService => true; + + [Fact] + public void ExplicitServiceRegistrationWithIsKeyedService() + { + if (!SupportsIServiceProviderIsKeyedService) + { + return; + } + + // Arrange + var key = new object(); + var collection = new TestServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeService), key, typeof(FakeService)); + var provider = CreateServiceProvider(collection); + + // Act + var serviceProviderIsService = provider.GetService(); + + // Assert + Assert.NotNull(serviceProviderIsService); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IFakeService), key)); + Assert.False(serviceProviderIsService.IsKeyedService(typeof(FakeService), new object())); + } + + [Fact] + public void OpenGenericsWithIsKeyedService() + { + if (!SupportsIServiceProviderIsKeyedService) + { + return; + } + + // Arrange + var key = new object(); + var collection = new TestServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeOpenGenericService<>), key, typeof(FakeOpenGenericService<>)); + var provider = CreateServiceProvider(collection); + + // Act + var serviceProviderIsService = provider.GetService(); + + // Assert + Assert.NotNull(serviceProviderIsService); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IFakeOpenGenericService), key)); + Assert.False(serviceProviderIsService.IsKeyedService(typeof(IFakeOpenGenericService<>), new object())); + } + + [Fact] + public void ClosedGenericsWithIsKeyedService() + { + if (!SupportsIServiceProviderIsKeyedService) + { + return; + } + + // Arrange + var key = new object(); + var collection = new TestServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeOpenGenericService), key, typeof(FakeOpenGenericService)); + var provider = CreateServiceProvider(collection); + + // Act + var serviceProviderIsService = provider.GetService(); + + // Assert + Assert.NotNull(serviceProviderIsService); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IFakeOpenGenericService), key)); + } + + [Fact] + public void IEnumerableWithIsKeyedServiceAlwaysReturnsTrue() + { + if (!SupportsIServiceProviderIsKeyedService) + { + return; + } + + // Arrange + var key = new object(); + var collection = new TestServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeService), typeof(FakeService)); + var provider = CreateServiceProvider(collection); + + // Act + var serviceProviderIsService = provider.GetService(); + + // Assert + Assert.NotNull(serviceProviderIsService); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IEnumerable), key)); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IEnumerable), key)); + Assert.False(serviceProviderIsService.IsKeyedService(typeof(IEnumerable<>), new object())); + } + + [Fact] + public void NonKeyedServiceWithIsKeyedService() + { + if (!SupportsIServiceProviderIsKeyedService) + { + return; + } + + // Arrange + var collection = new TestServiceCollection(); + collection.AddKeyedTransient(typeof(IFakeService), null, typeof(FakeService)); + var provider = CreateServiceProvider(collection); + + // Act + var serviceProviderIsService = provider.GetService(); + + // Assert + Assert.NotNull(serviceProviderIsService); + Assert.True(serviceProviderIsService.IsKeyedService(typeof(IFakeService), null)); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 495490bc9ff84..3034843eac9b2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { - internal sealed class CallSiteFactory : IServiceProviderIsService, IKeyedServiceProviderIsService + internal sealed class CallSiteFactory : IServiceProviderIsService, IServiceProviderIsKeyedService { private const int DefaultSlot = 0; private readonly ServiceDescriptor[] _descriptors; @@ -685,7 +685,8 @@ internal bool IsService(ServiceIdentifier serviceIdentifier) // If you update these make sure to also update the code in ServiceProvider.ctor return serviceType == typeof(IServiceProvider) || serviceType == typeof(IServiceScopeFactory) || - serviceType == typeof(IServiceProviderIsService); + serviceType == typeof(IServiceProviderIsService) || + serviceType == typeof(IServiceProviderIsKeyedService); } /// diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index dc523a38c57f2..613305cca6e5c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -58,6 +58,7 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceProvider)), new ServiceProviderCallSite()); CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceScopeFactory)), new ConstantCallSite(typeof(IServiceScopeFactory), Root)); CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceProviderIsService)), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory)); + CallSiteFactory.Add(ServiceIdentifier.FromServiceType(typeof(IServiceProviderIsKeyedService)), new ConstantCallSite(typeof(IServiceProviderIsKeyedService), CallSiteFactory)); if (options.ValidateScopes) { From 17b9312674fb7c4380e02741d8efa07cd7a6b84b Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 20:09:07 +0200 Subject: [PATCH 36/43] Fix ServiceDescriptor.DebuggerToString() --- .../src/ServiceDescriptor.cs | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index d8856f0e832ec..c551e7ba0b04a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -1012,17 +1012,36 @@ private string DebuggerToString() string debugText = $@"Lifetime = {Lifetime}, ServiceType = ""{ServiceType.FullName}"""; // Either implementation type, factory or instance is set. - if (ImplementationType != null) - { - debugText += $@", ImplementationType = ""{ImplementationType.FullName}"""; - } - else if (ImplementationFactory != null) + if (IsKeyedService) { - debugText += $@", ImplementationFactory = {ImplementationFactory.Method}"; + debugText += $@", ServiceKey = ""{ServiceKey}"""; + if (KeyedImplementationType != null) + { + debugText += $@", KeyedImplementationType = ""{KeyedImplementationType.FullName}"""; + } + else if (KeyedImplementationFactory != null) + { + debugText += $@", KeyedImplementationFactory = {KeyedImplementationFactory.Method}"; + } + else + { + debugText += $@", KeyedImplementationInstance = {KeyedImplementationInstance}"; + } } else { - debugText += $@", ImplementationInstance = {ImplementationInstance}"; + if (ImplementationType != null) + { + debugText += $@", ImplementationType = ""{ImplementationType.FullName}"""; + } + else if (ImplementationFactory != null) + { + debugText += $@", ImplementationFactory = {ImplementationFactory.Method}"; + } + else + { + debugText += $@", ImplementationInstance = {ImplementationInstance}"; + } } return debugText; From ccbedc6541033e9b9b45f9783fa2d0df2fd845b5 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 21:06:16 +0200 Subject: [PATCH 37/43] Fix IEnumerableWithIsKeyedServiceAlwaysReturnsTrue --- .../src/ServiceProviderIsKeyedServiceSpecificationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs index c7a9fa469ae28..7321fe0e1874c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/ServiceProviderIsKeyedServiceSpecificationTests.cs @@ -92,7 +92,7 @@ public void IEnumerableWithIsKeyedServiceAlwaysReturnsTrue() // Arrange var key = new object(); var collection = new TestServiceCollection(); - collection.AddKeyedTransient(typeof(IFakeService), typeof(FakeService)); + collection.AddKeyedTransient(typeof(IFakeService), key, typeof(FakeService)); var provider = CreateServiceProvider(collection); // Act From db15ad73e13de103612fabe21fa5d47b76af6609 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Wed, 5 Jul 2023 21:56:10 +0200 Subject: [PATCH 38/43] Fix ActivatorUtilities support of FromKeyedServicesAttribute --- .../src/ActivatorUtilities.cs | 51 ++++++++++++++++++- ...edDependencyInjectionSpecificationTests.cs | 17 +++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs index 30496b03be9b7..43e8f5627a2d2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs @@ -476,6 +476,53 @@ private static bool TryCreateParameterMap(ParameterInfo[] constructorParameters, return true; } + private static object? GetService(IServiceProvider serviceProvider, ParameterInfo parameterInfo) + { + // Handle keyed service + if (TryGetServiceKey(parameterInfo, out object? key)) + { + if (serviceProvider is IKeyedServiceProvider keyedServiceProvider) + { + return keyedServiceProvider.GetKeyedService(parameterInfo.ParameterType, key); + } + throw new InvalidOperationException(SR.KeyedServicesNotSupported); + } + // Try non keyed service + return serviceProvider.GetService(parameterInfo.ParameterType); + } + + private static bool IsService(IServiceProviderIsService serviceProviderIsService, ParameterInfo parameterInfo) + { + // Handle keyed service + if (TryGetServiceKey(parameterInfo, out object? key)) + { + if (serviceProviderIsService is IServiceProviderIsKeyedService serviceProviderIsKeyedService) + { + return serviceProviderIsKeyedService.IsKeyedService(parameterInfo.ParameterType, key); + } + throw new InvalidOperationException(SR.KeyedServicesNotSupported); + } + // Try non keyed service + return serviceProviderIsService.IsService(parameterInfo.ParameterType); + } + + private static bool TryGetServiceKey(ParameterInfo parameterInfo, out object? key) + { + if (parameterInfo.CustomAttributes != null) + { + foreach (var attribute in parameterInfo.GetCustomAttributes(true)) + { + if (attribute is FromKeyedServicesAttribute keyed) + { + key = keyed.Key; + return true; + } + } + } + key = null; + return false; + } + private readonly struct ConstructorMatcher { private readonly ConstructorInfo _constructor; @@ -517,7 +564,7 @@ public int Match(object[] givenParameters, IServiceProviderIsService serviceProv for (int i = 0; i < _parameters.Length; i++) { if (_parameterValues[i] == null && - !serviceProviderIsService.IsService(_parameters[i].ParameterType)) + !IsService(serviceProviderIsService, _parameters[i])) { if (ParameterDefaultValue.TryGetDefaultValue(_parameters[i], out object? defaultValue)) { @@ -539,7 +586,7 @@ public object CreateInstance(IServiceProvider provider) { if (_parameterValues[index] == null) { - object? value = provider.GetService(_parameters[index].ParameterType); + object? value = GetService(provider, _parameters[index]); if (value == null) { if (!ParameterDefaultValue.TryGetDefaultValue(_parameters[index], out object? defaultValue)) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs index 7dec0df829278..3aa328269d829 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs @@ -205,6 +205,23 @@ public void ResolveKeyedServiceSingletonInstanceWithKeyedParameter() Assert.Equal("service2", svc.Service2.ToString()); } + [Fact] + public void CreateServiceWithKeyedParameter() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(); + serviceCollection.AddKeyedSingleton("service1"); + serviceCollection.AddKeyedSingleton("service2"); + + var provider = CreateServiceProvider(serviceCollection); + + Assert.Null(provider.GetService()); + var svc = ActivatorUtilities.CreateInstance(provider); + Assert.NotNull(svc); + Assert.Equal("service1", svc.Service1.ToString()); + Assert.Equal("service2", svc.Service2.ToString()); + } + [Fact] public void ResolveKeyedServiceSingletonFactory() { From ec9b7ef852537f5d29baa806433eb3a8939fda4c Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 10 Jul 2023 18:07:04 +0200 Subject: [PATCH 39/43] Minor fixes --- .../Microsoft.Extensions.DependencyInjection.Abstractions.cs | 2 -- .../Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index d3695a9f7711e..bca117f391ca5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -4,8 +4,6 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System; - namespace Microsoft.Extensions.DependencyInjection { public static partial class ActivatorUtilities diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs index 4a4a6f92675d9..47edbf7b00c38 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs @@ -7,9 +7,6 @@ namespace Microsoft.Extensions.DependencyInjection.Extensions { - /// - /// Extension methods for adding and removing services to an . - /// public static partial class ServiceCollectionDescriptorExtensions { /// From 3a0a306622f046a3ecf34676855bd466ce781d8d Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Mon, 10 Jul 2023 20:28:46 +0200 Subject: [PATCH 40/43] Remove CompatibilitySuppressions.xml --- ...nsions.DependencyInjection.Abstractions.cs | 2 +- .../src/CompatibilitySuppressions.xml | 82 ------------------- 2 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index bca117f391ca5..72a89f8edb2a8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -59,7 +59,7 @@ public partial interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } - public partial interface IKeyedServiceProvider : IServiceProvider + public partial interface IKeyedServiceProvider : System.IServiceProvider { object? GetKeyedService(System.Type serviceType, object? serviceKey); object GetRequiredKeyedService(System.Type serviceType, object? serviceKey); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml deleted file mode 100644 index 2199b993a9836..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ObjectFactory.#ctor(System.Object,System.IntPtr) - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_IsKeyedService - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_KeyedServiceType - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll - - From 44e2fea3085f2ba4a15d9a91455d9f44d5e216ad Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 11 Jul 2023 21:09:45 +0200 Subject: [PATCH 41/43] Rollback CompatibilitySuppressions.xml --- .../src/CompatibilitySuppressions.xml | 109 +----------------- 1 file changed, 1 insertion(+), 108 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml index 7cbfeefce99e3..42539183a5a05 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml @@ -1,114 +1,7 @@  - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.dll - lib/net462/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/net462/Microsoft.Extensions.DependencyInjection.dll - lib/net462/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/net6.0/Microsoft.Extensions.DependencyInjection.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/net7.0/Microsoft.Extensions.DependencyInjection.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/net8.0/Microsoft.Extensions.DependencyInjection.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetKeyedService(System.Type,System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.ServiceProvider.GetRequiredKeyedService(System.Type,System.Object) - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/net462/Microsoft.Extensions.DependencyInjection.dll - lib/net462/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/net6.0/Microsoft.Extensions.DependencyInjection.dll - lib/net6.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/net7.0/Microsoft.Extensions.DependencyInjection.dll - lib/net7.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/net8.0/Microsoft.Extensions.DependencyInjection.dll - lib/net8.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll - - - CP0008 - T:Microsoft.Extensions.DependencyInjection.ServiceProvider - ref/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll - + CP0014 M:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.DependencyInjection.ServiceProviderOptions):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] From f7680e4f159e14d375905186e32080a1be1a378f Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 11 Jul 2023 21:40:47 +0200 Subject: [PATCH 42/43] Add tests --- ...iceCollectionKeyedServiceExtensionsTest.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs index e3f7110b2c296..1478a882209c8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs @@ -430,5 +430,67 @@ public void RemoveAll_RemovesAllServicesWithMatchingServiceType() // Assert Assert.Equal(new[] { descriptor }, collection); } + + [Fact] + public void NullServiceKey_ThrowsErrorWithFactory() + { + Assert.Throws(() => + new ServiceDescriptor( + typeof(IFakeService), + null, + (sp, key) => new FakeService(), ServiceLifetime.Transient)); + } + + public static TheoryData NullServiceKeyData + { + get + { + var serviceType = typeof(IFakeService); + object key = null; + var implementationType = typeof(FakeService); + var objectType = typeof(object); + + return new TheoryData + { + { ServiceDescriptor.KeyedTransient(key) }, + { ServiceDescriptor.KeyedScoped(key) }, + { ServiceDescriptor.KeyedSingleton(key) }, + { ServiceDescriptor.KeyedSingleton(key, new FakeService()) }, + }; + } + } + + [Theory] + [MemberData(nameof(NullServiceKeyData))] + public void NullServiceKey_IsKeyedServiceFalse(ServiceDescriptor serviceDescriptor) + { + Assert.False(serviceDescriptor.IsKeyedService); + } + + public static TheoryData NotNullServiceKeyData + { + get + { + var serviceType = typeof(IFakeService); + object key = new(); + var implementationType = typeof(FakeService); + var objectType = typeof(object); + + return new TheoryData + { + { ServiceDescriptor.KeyedTransient(key) }, + { ServiceDescriptor.KeyedScoped(key) }, + { ServiceDescriptor.KeyedSingleton(key) }, + { ServiceDescriptor.KeyedSingleton(key, new FakeService()) }, + }; + } + } + + [Theory] + [MemberData(nameof(NotNullServiceKeyData))] + public void NotNullServiceKey_IsKeyedServiceTrue(ServiceDescriptor serviceDescriptor) + { + Assert.True(serviceDescriptor.IsKeyedService); + } } } From d9a0270e5f19494fdb71f50da7a0d21915df60e9 Mon Sep 17 00:00:00 2001 From: Benjamin Petit Date: Tue, 11 Jul 2023 22:05:56 +0200 Subject: [PATCH 43/43] Make serviceKey nullable even when using a factory --- ...nsions.DependencyInjection.Abstractions.cs | 4 +- ...iceCollectionDescriptorExtensions.Keyed.cs | 24 ++++----- ...erviceCollectionServiceExtensions.Keyed.cs | 40 +++++++-------- .../src/ServiceDescriptor.cs | 50 +++++++++++-------- ...iceCollectionKeyedServiceExtensionsTest.cs | 20 ++++---- 5 files changed, 73 insertions(+), 65 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 72a89f8edb2a8..c9b3d241f0f23 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -145,7 +145,7 @@ public partial class ServiceDescriptor { public ServiceDescriptor(System.Type serviceType, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object instance) { } - public ServiceDescriptor(System.Type serviceType, object? serviceKey, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } + public ServiceDescriptor(System.Type serviceType, object? serviceKey, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object? serviceKey, object instance) { } public ServiceDescriptor(System.Type serviceType, object? serviceKey, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } @@ -154,7 +154,7 @@ public ServiceDescriptor(System.Type serviceType, [System.Diagnostics.CodeAnalys [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? ImplementationType { get { throw null; } } public bool IsKeyedService { get { throw null; } } - public System.Func? KeyedImplementationFactory { get { throw null; } } + public System.Func? KeyedImplementationFactory { get { throw null; } } public object? KeyedImplementationInstance { get { throw null; } } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public System.Type? KeyedImplementationType { get { throw null; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs index 47edbf7b00c38..aad0b4ff2fe41 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs @@ -63,8 +63,8 @@ public static void TryAddKeyedTransient( public static void TryAddKeyedTransient( this IServiceCollection collection, Type service, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -118,8 +118,8 @@ public static void TryAddKeyedTransient( /// The factory that creates the service. public static void TryAddKeyedTransient( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.KeyedTransient(serviceKey, implementationFactory)); @@ -179,8 +179,8 @@ public static void TryAddKeyedScoped( public static void TryAddKeyedScoped( this IServiceCollection collection, Type service, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -234,8 +234,8 @@ public static void TryAddKeyedScoped( /// The service key. public static void TryAddKeyedScoped( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.KeyedScoped(serviceKey, implementationFactory)); @@ -295,8 +295,8 @@ public static void TryAddKeyedSingleton( public static void TryAddKeyedSingleton( this IServiceCollection collection, Type service, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(collection); ThrowHelper.ThrowIfNull(service); @@ -369,8 +369,8 @@ public static void TryAddKeyedSingleton(this IServiceCollection collec /// The factory that creates the service. public static void TryAddKeyedSingleton( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { services.TryAdd(ServiceDescriptor.KeyedSingleton(serviceKey, implementationFactory)); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs index edec7feb8cfef..788b20f5be193 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.Keyed.cs @@ -49,8 +49,8 @@ public static IServiceCollection AddKeyedTransient( public static IServiceCollection AddKeyedTransient( this IServiceCollection services, Type serviceType, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -133,8 +133,8 @@ public static IServiceCollection AddKeyedTransient( /// public static IServiceCollection AddKeyedTransient( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -158,8 +158,8 @@ public static IServiceCollection AddKeyedTransient( /// public static IServiceCollection AddKeyedTransient( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -207,8 +207,8 @@ public static IServiceCollection AddKeyedScoped( public static IServiceCollection AddKeyedScoped( this IServiceCollection services, Type serviceType, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -291,8 +291,8 @@ public static IServiceCollection AddKeyedScoped( /// public static IServiceCollection AddKeyedScoped( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -316,8 +316,8 @@ public static IServiceCollection AddKeyedScoped( /// public static IServiceCollection AddKeyedScoped( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -366,8 +366,8 @@ public static IServiceCollection AddKeyedSingleton( public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, Type serviceType, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(services); ThrowHelper.ThrowIfNull(serviceType); @@ -450,8 +450,8 @@ public static IServiceCollection AddKeyedSingleton( /// public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(services); @@ -475,8 +475,8 @@ public static IServiceCollection AddKeyedSingleton( /// public static IServiceCollection AddKeyedSingleton( this IServiceCollection services, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -549,8 +549,8 @@ private static IServiceCollection AddKeyed( private static IServiceCollection AddKeyed( IServiceCollection collection, Type serviceType, - object serviceKey, - Func implementationFactory, + object? serviceKey, + Func implementationFactory, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, serviceKey, implementationFactory, lifetime); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index c551e7ba0b04a..4edb491cc6ccf 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -106,16 +106,24 @@ public ServiceDescriptor( /// The of the service. public ServiceDescriptor( Type serviceType, - object serviceKey, - Func factory, + object? serviceKey, + Func factory, ServiceLifetime lifetime) : this(serviceType, serviceKey, lifetime) { ThrowHelper.ThrowIfNull(serviceType); - ThrowHelper.ThrowIfNull(serviceKey); ThrowHelper.ThrowIfNull(factory); - _implementationFactory = factory; + if (serviceKey is null) + { + // If the key is null, use the same factory signature as non-keyed descriptor + Func nullKeyedFactory = sp => factory(sp, null); + _implementationFactory = nullKeyedFactory; + } + else + { + _implementationFactory = factory; + } } private ServiceDescriptor(Type serviceType, object? serviceKey, ServiceLifetime lifetime) @@ -227,7 +235,7 @@ public Func? ImplementationFactory /// /// Gets the factory used for creating Keyed service instances. /// - public Func? KeyedImplementationFactory + public Func? KeyedImplementationFactory { get { @@ -235,7 +243,7 @@ public Func? KeyedImplementationFactory { ThrowNonKeyedDescriptor(); } - return (Func?) _implementationFactory; + return (Func?) _implementationFactory; } } @@ -424,8 +432,8 @@ public static ServiceDescriptor Transient( /// A factory to create new instances of the service implementation. /// A new instance of . public static ServiceDescriptor KeyedTransient( - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -459,7 +467,7 @@ public static ServiceDescriptor Transient(FuncThe of the service. /// A factory to create new instances of the service implementation. /// A new instance of . - public static ServiceDescriptor KeyedTransient(object serviceKey, Func implementationFactory) + public static ServiceDescriptor KeyedTransient(object? serviceKey, Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(implementationFactory); @@ -492,7 +500,7 @@ public static ServiceDescriptor Transient(Type service, FuncThe of the service. /// A factory to create new instances of the service implementation. /// A new instance of . - public static ServiceDescriptor KeyedTransient(Type service, object serviceKey, Func implementationFactory) + public static ServiceDescriptor KeyedTransient(Type service, object? serviceKey, Func implementationFactory) { ThrowHelper.ThrowIfNull(service); ThrowHelper.ThrowIfNull(implementationFactory); @@ -595,8 +603,8 @@ public static ServiceDescriptor Scoped( /// A factory to create new instances of the service implementation. /// A new instance of . public static ServiceDescriptor KeyedScoped( - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -630,7 +638,7 @@ public static ServiceDescriptor Scoped(FuncThe of the service. /// A factory to create new instances of the service implementation. /// A new instance of . - public static ServiceDescriptor KeyedScoped(object serviceKey, Func implementationFactory) + public static ServiceDescriptor KeyedScoped(object? serviceKey, Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(implementationFactory); @@ -663,7 +671,7 @@ public static ServiceDescriptor Scoped(Type service, FuncThe of the service. /// A factory to create new instances of the service implementation. /// A new instance of . - public static ServiceDescriptor KeyedScoped(Type service, object serviceKey, Func implementationFactory) + public static ServiceDescriptor KeyedScoped(Type service, object? serviceKey, Func implementationFactory) { ThrowHelper.ThrowIfNull(service); ThrowHelper.ThrowIfNull(implementationFactory); @@ -773,8 +781,8 @@ public static ServiceDescriptor Singleton( /// A factory to create new instances of the service implementation. /// A new instance of . public static ServiceDescriptor KeyedSingleton( - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class where TImplementation : class, TService { @@ -809,8 +817,8 @@ public static ServiceDescriptor Singleton(FuncA factory to create new instances of the service implementation. /// A new instance of . public static ServiceDescriptor KeyedSingleton( - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) where TService : class { ThrowHelper.ThrowIfNull(implementationFactory); @@ -847,8 +855,8 @@ public static ServiceDescriptor Singleton( /// A new instance of . public static ServiceDescriptor KeyedSingleton( Type serviceType, - object serviceKey, - Func implementationFactory) + object? serviceKey, + Func implementationFactory) { ThrowHelper.ThrowIfNull(serviceType); ThrowHelper.ThrowIfNull(implementationFactory); @@ -1002,7 +1010,7 @@ public static ServiceDescriptor Describe(Type serviceType, FuncA factory to create new instances of the service implementation. /// The lifetime of the service. /// A new instance of . - public static ServiceDescriptor DescribeKeyed(Type serviceType, object serviceKey, Func implementationFactory, ServiceLifetime lifetime) + public static ServiceDescriptor DescribeKeyed(Type serviceType, object? serviceKey, Func implementationFactory, ServiceLifetime lifetime) { return new ServiceDescriptor(serviceType, serviceKey, implementationFactory, lifetime); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs index 1478a882209c8..25b61065ef0ba 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs @@ -431,16 +431,6 @@ public void RemoveAll_RemovesAllServicesWithMatchingServiceType() Assert.Equal(new[] { descriptor }, collection); } - [Fact] - public void NullServiceKey_ThrowsErrorWithFactory() - { - Assert.Throws(() => - new ServiceDescriptor( - typeof(IFakeService), - null, - (sp, key) => new FakeService(), ServiceLifetime.Transient)); - } - public static TheoryData NullServiceKeyData { get @@ -453,7 +443,9 @@ public static TheoryData NullServiceKeyData return new TheoryData { { ServiceDescriptor.KeyedTransient(key) }, + { ServiceDescriptor.KeyedTransient(key, (sp, key) => new FakeService()) }, { ServiceDescriptor.KeyedScoped(key) }, + { ServiceDescriptor.KeyedScoped(key, (sp, key) => new FakeService()) }, { ServiceDescriptor.KeyedSingleton(key) }, { ServiceDescriptor.KeyedSingleton(key, new FakeService()) }, }; @@ -465,6 +457,9 @@ public static TheoryData NullServiceKeyData public void NullServiceKey_IsKeyedServiceFalse(ServiceDescriptor serviceDescriptor) { Assert.False(serviceDescriptor.IsKeyedService); + Assert.Throws(() => serviceDescriptor.KeyedImplementationInstance); + Assert.Throws(() => serviceDescriptor.KeyedImplementationType); + Assert.Throws(() => serviceDescriptor.KeyedImplementationFactory); } public static TheoryData NotNullServiceKeyData @@ -479,7 +474,9 @@ public static TheoryData NotNullServiceKeyData return new TheoryData { { ServiceDescriptor.KeyedTransient(key) }, + { ServiceDescriptor.KeyedTransient(key, (sp, key) => new FakeService()) }, { ServiceDescriptor.KeyedScoped(key) }, + { ServiceDescriptor.KeyedScoped(key, (sp, key) => new FakeService()) }, { ServiceDescriptor.KeyedSingleton(key) }, { ServiceDescriptor.KeyedSingleton(key, new FakeService()) }, }; @@ -491,6 +488,9 @@ public static TheoryData NotNullServiceKeyData public void NotNullServiceKey_IsKeyedServiceTrue(ServiceDescriptor serviceDescriptor) { Assert.True(serviceDescriptor.IsKeyedService); + Assert.Throws(() => serviceDescriptor.ImplementationInstance); + Assert.Throws(() => serviceDescriptor.ImplementationType); + Assert.Throws(() => serviceDescriptor.ImplementationFactory); } } }