Browse Source

Use the `ServiceIdentifier` structure to represent keyed services.

pull/18792/head
maliming 3 years ago
parent
commit
8e139403fe
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 19
      framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs
  2. 45
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs
  3. 50
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs
  4. 4
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs
  5. 16
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs

19
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.");
}
}

45
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs

@ -2,28 +2,53 @@ using System;
namespace Volo.Abp.DependencyInjection;
public class CachedServiceDescriptor
/// <summary>
/// https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceIdentifier.cs#L9
/// </summary>
public readonly struct ServiceIdentifier : IEquatable<ServiceIdentifier>
{
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();
}
}
}

50
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<CachedServiceDescriptor, Lazy<object?>> CachedServices { get; }
protected ConcurrentDictionary<ServiceIdentifier, Lazy<object?>> CachedServices { get; }
protected CachedServiceProviderBase(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
CachedServices = new ConcurrentDictionary<CachedServiceDescriptor, Lazy<object?>>();
CachedServices.TryAdd(new CachedServiceDescriptor(null, typeof(IServiceProvider)), new Lazy<object?>(() => ServiceProvider));
CachedServices = new ConcurrentDictionary<ServiceIdentifier, Lazy<object?>>();
CachedServices.TryAdd(new ServiceIdentifier(typeof(IServiceProvider)), new Lazy<object?>(() => ServiceProvider));
}
public virtual object? GetService(Type serviceType)
{
return CachedServices.GetOrAdd(
new CachedServiceDescriptor(null, serviceType),
new ServiceIdentifier(serviceType),
_ => new Lazy<object?>(() => ServiceProvider.GetService(serviceType))
).Value;
}
@ -42,44 +42,24 @@ public abstract class CachedServiceProviderBase : ICachedServiceProviderBase
public object GetService(Type serviceType, Func<IServiceProvider, object> factory)
{
return CachedServices.GetOrAdd(
new CachedServiceDescriptor(null, serviceType),
new ServiceIdentifier(serviceType),
_ => new Lazy<object?>(() => factory(ServiceProvider))
).Value!;
}
public virtual T GetKeyedService<T>(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<object?>(() => requiredServiceSupportingProvider.GetKeyedService(serviceType, serviceKey))
).Value;
}
throw new InvalidOperationException("This service provider doesn't support keyed services.");
}
public virtual T GetRequiredKeyedService<T>(object? serviceKey)
{
return (T)GetRequiredKeyedService(typeof(T), serviceKey);
return CachedServices.GetOrAdd(
new ServiceIdentifier(serviceKey, serviceType),
_ => new Lazy<object?>(() => 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<object?>(() => 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<object?>(() => ServiceProvider.GetRequiredKeyedService(serviceType, serviceKey))
).Value!;
}
}

4
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs

@ -12,8 +12,4 @@ public interface ICachedServiceProviderBase : IKeyedServiceProvider
T GetService<T>(Func<IServiceProvider, object> factory);
object GetService(Type serviceType, Func<IServiceProvider, object> factory);
T GetKeyedService<T>(object? serviceKey);
T GetRequiredKeyedService<T>(object? serviceKey);
}

16
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);
}
}

Loading…
Cancel
Save