diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs index 363c3b3885..3aff8a78ad 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs @@ -1,19 +1,13 @@ using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.DependencyInjection; -public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDependency +[ExposeServices(typeof(IAbpLazyServiceProvider))] +public class AbpLazyServiceProvider : CachedServiceProviderBase, IAbpLazyServiceProvider, ITransientDependency { - protected IDictionary CachedServices { get; set; } - - protected IServiceProvider ServiceProvider { get; set; } - public AbpLazyServiceProvider(IServiceProvider serviceProvider) + : base(serviceProvider) { - ServiceProvider = serviceProvider; - CachedServices = new Dictionary(); } public virtual T LazyGetRequiredService() @@ -23,7 +17,7 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetRequiredService(Type serviceType) { - return CachedServices.GetOrAdd(serviceType, () => ServiceProvider.GetRequiredService(serviceType)); + return GetService(serviceType); } public virtual T LazyGetService() @@ -33,7 +27,7 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetService(Type serviceType) { - return CachedServices.GetOrAdd(serviceType, () => ServiceProvider.GetService(serviceType)); + return GetService(serviceType); } public virtual T LazyGetService(T defaultValue) @@ -53,6 +47,9 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetService(Type serviceType, Func factory) { - return CachedServices.GetOrAdd(serviceType, () => factory(ServiceProvider)); + return CachedServices.GetOrAdd( + serviceType, + _ => new Lazy(() => factory(ServiceProvider)) + ).Value; } } 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 d543493ce9..c261d3a3bb 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs @@ -5,21 +5,21 @@ namespace Volo.Abp.DependencyInjection; public abstract class CachedServiceProviderBase { - private readonly IServiceProvider _serviceProvider; - private readonly ConcurrentDictionary> _cachedServices; + protected IServiceProvider ServiceProvider { get; } + protected ConcurrentDictionary> CachedServices { get; } protected CachedServiceProviderBase(IServiceProvider serviceProvider) { - _serviceProvider = serviceProvider; - _cachedServices = new ConcurrentDictionary>(); - _cachedServices.TryAdd(typeof(IServiceProvider), new Lazy(() => _serviceProvider)); + ServiceProvider = serviceProvider; + CachedServices = new ConcurrentDictionary>(); + CachedServices.TryAdd(typeof(IServiceProvider), new Lazy(() => ServiceProvider)); } public virtual object GetService(Type serviceType) { - return _cachedServices.GetOrAdd( + return CachedServices.GetOrAdd( serviceType, - _ => new Lazy(() => _serviceProvider.GetService(serviceType)) + _ => new Lazy(() => ServiceProvider.GetService(serviceType)) ).Value; } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs new file mode 100644 index 0000000000..c78dc9c989 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs @@ -0,0 +1,50 @@ +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.Testing.Utils; +using Xunit; + +namespace Volo.Abp.DependencyInjection; + +public class AbpLazyServiceProvider_Tests +{ + [Fact] + public void LazyServiceProvider_Should_Cache_Services() + { + using (var application = AbpApplicationFactory.Create()) + { + application.Initialize(); + + var lazyServiceProvider = application.ServiceProvider.GetRequiredService(); + + var transientTestService1 = lazyServiceProvider.LazyGetRequiredService(); + var transientTestService2 = lazyServiceProvider.LazyGetRequiredService(); + transientTestService1.ShouldBeSameAs(transientTestService2); + + var testCounter = application.ServiceProvider.GetRequiredService(); + testCounter.GetValue(nameof(TransientTestService)).ShouldBe(1); + } + } + + [DependsOn(typeof(AbpTestBaseModule))] + private class TestModule : AbpModule + { + public TestModule() + { + SkipAutoServiceRegistration = true; + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddType(); + } + } + + private class TransientTestService : ITransientDependency + { + public TransientTestService(ITestCounter counter) + { + counter.Increment(nameof(TransientTestService)); + } + } +}