From 8e139403feb7f0660c3940d1adc6a2cf09c39506 Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 20 Jan 2024 09:44:44 +0800 Subject: [PATCH] Use the `ServiceIdentifier` structure to represent keyed services. --- .../ServiceProviderKeyedServiceExtensions.cs | 19 +++++++ .../CachedServiceDescriptor.cs | 45 +++++++++++++---- .../CachedServiceProviderBase.cs | 50 ++++++------------- .../ICachedServiceProviderBase.cs | 4 -- .../RootServiceProvider.cs | 16 ++---- 5 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs new file mode 100644 index 0000000000..f31923f68c --- /dev/null +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Volo.Abp; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class ServiceProviderKeyedServiceExtensions +{ + public static object? GetKeyedService(this IServiceProvider provider, Type serviceType, object? serviceKey) + { + Check.NotNull(provider, nameof(provider)); + + if (provider is IKeyedServiceProvider keyedServiceProvider) + { + return keyedServiceProvider.GetKeyedService(serviceType, serviceKey); + } + + throw new InvalidOperationException("This service provider doesn't support keyed services."); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs index 1b812fc4a2..b6dbcd8a02 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs @@ -2,28 +2,53 @@ using System; namespace Volo.Abp.DependencyInjection; -public class CachedServiceDescriptor +/// +/// https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceIdentifier.cs#L9 +/// +public readonly struct ServiceIdentifier : IEquatable { - private object? Key { get; } + public object? ServiceKey { get; } - private Type ServiceType { get; } + public Type ServiceType { get; } - public CachedServiceDescriptor(object? key, Type serviceType) + public ServiceIdentifier(Type serviceType) { - Key = key; ServiceType = serviceType; } + public ServiceIdentifier(object? serviceKey, Type serviceType) + { + ServiceKey = serviceKey; + ServiceType = serviceType; + } + + public bool Equals(ServiceIdentifier other) + { + if (ServiceKey == null && other.ServiceKey == null) + { + return ServiceType == other.ServiceType; + } + else if (ServiceKey != null && other.ServiceKey != null) + { + return ServiceType == other.ServiceType && ServiceKey.Equals(other.ServiceKey); + } + return false; + } + public override bool Equals(object? obj) { - return obj is CachedServiceDescriptor descriptor && - Key == descriptor.Key && - ServiceType == descriptor.ServiceType; + return obj is ServiceIdentifier && Equals((ServiceIdentifier)obj); } public override int GetHashCode() { - var keyHashCode = Key?.GetHashCode() ?? 0; - return keyHashCode ^ ServiceType.GetHashCode(); + if (ServiceKey == null) + { + return ServiceType.GetHashCode(); + } + unchecked + { + return (ServiceType.GetHashCode() * 397) ^ ServiceKey.GetHashCode(); + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs index 774efedb9a..770355428e 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs @@ -7,19 +7,19 @@ namespace Volo.Abp.DependencyInjection; public abstract class CachedServiceProviderBase : ICachedServiceProviderBase { protected IServiceProvider ServiceProvider { get; } - protected ConcurrentDictionary> CachedServices { get; } + protected ConcurrentDictionary> CachedServices { get; } protected CachedServiceProviderBase(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; - CachedServices = new ConcurrentDictionary>(); - CachedServices.TryAdd(new CachedServiceDescriptor(null, typeof(IServiceProvider)), new Lazy(() => ServiceProvider)); + CachedServices = new ConcurrentDictionary>(); + CachedServices.TryAdd(new ServiceIdentifier(typeof(IServiceProvider)), new Lazy(() => ServiceProvider)); } public virtual object? GetService(Type serviceType) { return CachedServices.GetOrAdd( - new CachedServiceDescriptor(null, serviceType), + new ServiceIdentifier(serviceType), _ => new Lazy(() => ServiceProvider.GetService(serviceType)) ).Value; } @@ -42,44 +42,24 @@ public abstract class CachedServiceProviderBase : ICachedServiceProviderBase public object GetService(Type serviceType, Func factory) { return CachedServices.GetOrAdd( - new CachedServiceDescriptor(null, serviceType), + new ServiceIdentifier(serviceType), _ => new Lazy(() => factory(ServiceProvider)) ).Value!; } - public virtual T GetKeyedService(object? serviceKey) + public object? GetKeyedService(Type serviceType, object? serviceKey) { - return (T)GetKeyedService(typeof(T), serviceKey)!; - } - - public virtual object? GetKeyedService(Type serviceType, object? serviceKey) - { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return CachedServices.GetOrAdd( - new CachedServiceDescriptor(serviceKey, serviceType), - _ => new Lazy(() => requiredServiceSupportingProvider.GetKeyedService(serviceType, serviceKey)) - ).Value; - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); - } - - public virtual T GetRequiredKeyedService(object? serviceKey) - { - return (T)GetRequiredKeyedService(typeof(T), serviceKey); + return CachedServices.GetOrAdd( + new ServiceIdentifier(serviceKey, serviceType), + _ => new Lazy(() => ServiceProvider.GetKeyedService(serviceType, serviceKey)) + ).Value; } - public virtual object GetRequiredKeyedService(Type serviceType, object? serviceKey) + public object GetRequiredKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return CachedServices.GetOrAdd( - new CachedServiceDescriptor(serviceKey, serviceType), - _ => new Lazy(() => requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey)) - ).Value!; - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return CachedServices.GetOrAdd( + new ServiceIdentifier(serviceKey, serviceType), + _ => new Lazy(() => ServiceProvider.GetRequiredKeyedService(serviceType, serviceKey)) + ).Value!; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs index 6fc281f430..ceec3326cc 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs @@ -12,8 +12,4 @@ public interface ICachedServiceProviderBase : IKeyedServiceProvider T GetService(Func factory); object GetService(Type serviceType, Func factory); - - T GetKeyedService(object? serviceKey); - - T GetRequiredKeyedService(object? serviceKey); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs index 53d5878ea4..7ba378d76a 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs @@ -18,23 +18,13 @@ public class RootServiceProvider : IRootServiceProvider, ISingletonDependency return ServiceProvider.GetService(serviceType); } - public virtual object? GetKeyedService(Type serviceType, object? serviceKey) + public object? GetKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return requiredServiceSupportingProvider.GetKeyedService(serviceType, serviceKey); - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return ServiceProvider.GetKeyedService(serviceType, serviceKey); } public virtual object GetRequiredKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey); - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return ServiceProvider.GetRequiredKeyedService(serviceType, serviceKey); } }