diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs index 15361ece62..5f4d64f512 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; @@ -24,13 +26,18 @@ namespace Volo.Abp.DependencyInjection return; } - var serviceTypes = ExposedServiceExplorer.GetExposedServices(type); + var exposedServiceTypes = ExposedServiceExplorer.GetExposedServices(type); - TriggerServiceExposing(services, type, serviceTypes); + TriggerServiceExposing(services, type, exposedServiceTypes); - foreach (var serviceType in serviceTypes) + foreach (var exposedServiceType in exposedServiceTypes) { - var serviceDescriptor = ServiceDescriptor.Describe(serviceType, type, lifeTime.Value); + var serviceDescriptor = CreateServiceDescriptor( + type, + exposedServiceType, + exposedServiceTypes, + lifeTime.Value + ); if (dependencyAttribute?.ReplaceServices == true) { @@ -46,7 +53,63 @@ namespace Volo.Abp.DependencyInjection } } } - + + protected virtual ServiceDescriptor CreateServiceDescriptor( + Type implementationType, + Type exposingServiceType, + List allExposingServiceTypes, + ServiceLifetime lifeTime) + { + if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped)) + { + var redirectedType = GetRedirectedTypeOrNull( + implementationType, + exposingServiceType, + allExposingServiceTypes + ); + + if (redirectedType != null) + { + return ServiceDescriptor.Describe( + exposingServiceType, + provider => provider.GetService(redirectedType), + lifeTime + ); + } + } + + return ServiceDescriptor.Describe( + exposingServiceType, + implementationType, + lifeTime + ); + } + + protected virtual Type GetRedirectedTypeOrNull( + Type implementationType, + Type exposingServiceType, + List allExposingServiceTypes) + { + if (allExposingServiceTypes.Count < 2) + { + return null; + } + + if (exposingServiceType == implementationType) + { + return null; + } + + if (allExposingServiceTypes.Contains(implementationType)) + { + return implementationType; + } + + return allExposingServiceTypes.FirstOrDefault( + t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t) + ); + } + protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type) { return type.GetCustomAttribute(true); diff --git a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs index 680cb607f7..d6e9847cfc 100644 --- a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using Shouldly; -using Volo.Abp; using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Testing; @@ -63,6 +62,15 @@ namespace Microsoft.Extensions.DependencyInjection GetRequiredService().ProperyInjectedService.ShouldNotBeNull(); } + [Fact] + public void Singletons_Exposing_Multiple_Services_Should_Returns_The_Same_Instance() + { + var objectByInterfaceRef = GetRequiredService(); + var objectByClassRef = GetRequiredService(); + + ReferenceEquals(objectByInterfaceRef, objectByClassRef).ShouldBeTrue(); + } + public class MySingletonService : ISingletonDependency { public List TransientInstances { get; } @@ -116,6 +124,17 @@ namespace Microsoft.Extensions.DependencyInjection } } + public interface IMySingletonExposingMultipleServices + { + + } + + [ExposeServices(typeof(IMySingletonExposingMultipleServices), typeof(MySingletonExposingMultipleServices))] + public class MySingletonExposingMultipleServices : IMySingletonExposingMultipleServices, ISingletonDependency + { + + } + public class TestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -124,6 +143,7 @@ namespace Microsoft.Extensions.DependencyInjection context.Services.AddType(); context.Services.AddType(); context.Services.AddType(); + context.Services.AddType(); context.Services.AddTransient(typeof(GenericServiceWithPropertyInject<>)); context.Services.AddTransient(typeof(ConcreteGenericServiceWithPropertyInject)); }