diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/DependencyInjection_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/DependencyInjection_Tests.cs index 7e823dc3b1..8baf863b94 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/DependencyInjection_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/DependencyInjection_Tests.cs @@ -16,11 +16,11 @@ namespace Volo.Abp.DependencyInjection var services = new ServiceCollection(); services - .AddSingleton() + .AddSingleton() .AddTransient() .AddTransient(); - MySingletonService singletonService; + MySingletonServiceUsesTransients singletonService; using (var serviceProvider = services.BuildServiceProvider()) { @@ -36,21 +36,77 @@ namespace Volo.Abp.DependencyInjection { scope.ServiceProvider.GetRequiredService().DoIt(); scope.ServiceProvider.GetRequiredService().DoIt(); - scope.ServiceProvider.GetRequiredService().ShouldNotBeDisposed(); + scope.ServiceProvider.GetRequiredService().ShouldNotBeDisposed(); } - singletonService = serviceProvider.GetRequiredService(); + singletonService = serviceProvider.GetRequiredService(); singletonService.ShouldNotBeDisposed(); } singletonService.ShouldBeDisposed(); } + [Fact] + public void Should_Release_Resolved_Services_When_Main_Service_Is_Disposed() + { + var services = new ServiceCollection(); + + services + .AddTransient() + .AddTransient(); + + using (var serviceProvider = services.BuildServiceProvider()) + { + MyTransientServiceUsesTransients myTransientServiceUsesTransients; + + using (var scope = serviceProvider.CreateScope()) + { + myTransientServiceUsesTransients = scope.ServiceProvider.GetRequiredService(); + + myTransientServiceUsesTransients.DoIt(); + myTransientServiceUsesTransients.DoIt(); + + myTransientServiceUsesTransients.ShouldNotBeDisposed(); + } + + myTransientServiceUsesTransients.ShouldBeDisposed(); + } + } + + [Fact] + public void Inner_Scope_Should_Resolve_New_Scoped_Service() + { + var services = new ServiceCollection(); + + services + .AddScoped(); + + using (var serviceProvider = services.BuildServiceProvider()) + { + using (var scope = serviceProvider.CreateScope()) + { + var service1 = scope.ServiceProvider.GetRequiredService(); + var service2 = scope.ServiceProvider.GetRequiredService(); + + service1.ShouldBe(service2); + + using (var innerScope = scope.ServiceProvider.CreateScope()) + { + var innserService1 = innerScope.ServiceProvider.GetRequiredService(); + var innserService2 = innerScope.ServiceProvider.GetRequiredService(); + + innserService1.ShouldBe(innserService2); + innserService1.ShouldNotBe(service1); + } + } + } + } + private class MyTransientServiceUsesSingleton { - private readonly MySingletonService _singletonService; + private readonly MySingletonServiceUsesTransients _singletonService; - public MyTransientServiceUsesSingleton(MySingletonService singletonService) + public MyTransientServiceUsesSingleton(MySingletonServiceUsesTransients singletonService) { _singletonService = singletonService; } @@ -61,13 +117,13 @@ namespace Volo.Abp.DependencyInjection } } - private class MySingletonService + private class MySingletonServiceUsesTransients { private readonly IServiceProvider _serviceProvider; private readonly List _instances; - public MySingletonService(IServiceProvider serviceProvider) + public MySingletonServiceUsesTransients(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _instances = new List(); @@ -104,5 +160,59 @@ namespace Volo.Abp.DependencyInjection IsDisposed = true; } } + + private class MyTransientServiceUsesTransients + { + private readonly IServiceProvider _serviceProvider; + + private readonly List _instances; + + public MyTransientServiceUsesTransients(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + _instances = new List(); + } + + public void DoIt() + { + _instances.Add(_serviceProvider.GetRequiredService()); + } + + public void ShouldNotBeDisposed() + { + foreach (var instance in _instances) + { + instance.IsDisposed.ShouldBeFalse(); + } + } + + public void ShouldBeDisposed() + { + foreach (var instance in _instances) + { + instance.IsDisposed.ShouldBeTrue(); + } + } + } + + private class ScopedServiceWithState + { + private readonly Dictionary _items; + + public ScopedServiceWithState() + { + _items = new Dictionary(); + } + + public void Set(string name, object value) + { + _items[name] = value; + } + + public object Get(string name) + { + return _items[name]; + } + } } }