diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index f9a07ac3a4..8d4536fec9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.DependencyInjection; diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextServiceScopeFactory.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextServiceScopeFactory.cs new file mode 100644 index 0000000000..64952c3f97 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/DependencyInjection/HttpContextServiceScopeFactory.cs @@ -0,0 +1,53 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.DependencyInjection +{ + [ExposeServices( + typeof(IHybridServiceScopeFactory), + typeof(HttpContextServiceScopeFactory) + )] + [Dependency(ReplaceServices = true)] + public class HttpContextServiceScopeFactory : IHybridServiceScopeFactory, ITransientDependency + { + protected IHttpContextAccessor HttpContextAccessor { get; } + + protected IServiceScopeFactory ServiceScopeFactory { get; } + + public HttpContextServiceScopeFactory( + IHttpContextAccessor httpContextAccessor, + IServiceScopeFactory serviceScopeFactory) + { + HttpContextAccessor = httpContextAccessor; + ServiceScopeFactory = serviceScopeFactory; + } + + public virtual IServiceScope CreateScope() + { + var httpContext = HttpContextAccessor.HttpContext; + if (httpContext == null) + { + return ServiceScopeFactory.CreateScope(); + } + + return new NonDisposedHttpContextServiceScope(httpContext.RequestServices); + } + + protected class NonDisposedHttpContextServiceScope : IServiceScope + { + public IServiceProvider ServiceProvider { get; } + + public NonDisposedHttpContextServiceScope(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public void Dispose() + { + + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultServiceScopeFactory.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultServiceScopeFactory.cs new file mode 100644 index 0000000000..36af7a210a --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultServiceScopeFactory.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.DependencyInjection +{ + [ExposeServices( + typeof(IHybridServiceScopeFactory), + typeof(DefaultServiceScopeFactory) + )] + public class DefaultServiceScopeFactory : IHybridServiceScopeFactory, ITransientDependency + { + protected IServiceScopeFactory Factory { get; } + + public DefaultServiceScopeFactory(IServiceScopeFactory factory) + { + Factory = factory; + } + + public IServiceScope CreateScope() + { + return Factory.CreateScope(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IHybridServiceScopeFactory.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IHybridServiceScopeFactory.cs new file mode 100644 index 0000000000..207d7d33c2 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IHybridServiceScopeFactory.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.DependencyInjection +{ + public interface IHybridServiceScopeFactory : IServiceScopeFactory + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/TransientEventHandlerFactory.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/TransientEventHandlerFactory.cs index fe5bf8892e..6cacc3522d 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/TransientEventHandlerFactory.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/TransientEventHandlerFactory.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.EventBus /// /// This class always creates a new transient instance of handler. /// - internal class TransientEventHandlerFactory : IEventHandlerFactory + public class TransientEventHandlerFactory : IEventHandlerFactory where THandler : IEventHandler, new() { /// diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/HybridServiceScopeFactory_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/HybridServiceScopeFactory_Tests.cs new file mode 100644 index 0000000000..42bb7bb800 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/HybridServiceScopeFactory_Tests.cs @@ -0,0 +1,41 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.DependencyInjection +{ + public class HybridServiceScopeFactory_Tests + { + [Fact] + public void Should_Use_Default_ServiceScopeFactory_By_Default() + { + using (var application = AbpApplicationFactory.Create()) + { + application.Services.AddType(typeof(MyService)); + + application.Initialize(); + + var serviceScopeFactory = application.ServiceProvider.GetRequiredService(); + + using (var scope = serviceScopeFactory.CreateScope()) + { + scope.ServiceProvider.GetRequiredService(); + } + + MyService.DisposeCount.ShouldBe(1); + } + } + + private class MyService : ITransientDependency, IDisposable + { + public static int DisposeCount { get; private set; } + + public void Dispose() + { + ++DisposeCount; + } + } + } +}