Browse Source

Async configure and initialize the module.

pull/10928/head
maliming 5 years ago
parent
commit
8c5e3cd30a
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 22
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  2. 17
      framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionApplicationExtensions.cs
  3. 107
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs
  4. 3
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationCreationOptions.cs
  5. 55
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationFactory.cs
  6. 10
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs
  7. 7
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs
  8. 6
      framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplication.cs
  9. 13
      framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs
  10. 13
      framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs
  11. 5
      framework/src/Volo.Abp.Core/Volo/Abp/IOnApplicationInitialization.cs
  12. 5
      framework/src/Volo.Abp.Core/Volo/Abp/IOnApplicationShutdown.cs
  13. 43
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModule.cs
  14. 36
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DefaultModuleLifecycleContributor.cs
  15. 6
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs
  16. 7
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IModuleLifecycleContributor.cs
  17. 7
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IModuleManager.cs
  18. 5
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs
  19. 5
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs
  20. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IPostConfigureServices.cs
  21. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IPreConfigureServices.cs
  22. 14
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLifecycleContributorBase.cs
  23. 41
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs
  24. 82
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs
  25. 36
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/Configuration/ConfigurationAccessor_Tests.cs
  26. 15
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AutoServiceRegistration_Tests.cs
  27. 31
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/HybridServiceScopeFactory_Tests.cs
  28. 68
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/TestModuleBase.cs

22
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.RequestLocalization;
using Microsoft.Extensions.DependencyInjection;
@ -18,6 +19,27 @@ public static class AbpApplicationBuilderExtensions
{
private const string ExceptionHandlingMiddlewareMarker = "_AbpExceptionHandlingMiddleware_Added";
public async static Task InitializeApplicationAsync([NotNull] this IApplicationBuilder app)
{
Check.NotNull(app, nameof(app));
app.ApplicationServices.GetRequiredService<ObjectAccessor<IApplicationBuilder>>().Value = app;
var application = app.ApplicationServices.GetRequiredService<IAbpApplicationWithExternalServiceProvider>();
var applicationLifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
applicationLifetime.ApplicationStopping.Register(() =>
{
application.ShutdownAsync();
});
applicationLifetime.ApplicationStopped.Register(() =>
{
application.Dispose();
});
await application.InitializeAsync(app.ApplicationServices);
}
public static void InitializeApplication([NotNull] this IApplicationBuilder app)
{
Check.NotNull(app, nameof(app));

17
framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionApplicationExtensions.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Modularity;
@ -22,4 +23,20 @@ public static class ServiceCollectionApplicationExtensions
{
return AbpApplicationFactory.Create(startupModuleType, services, optionsAction);
}
public async static Task<IAbpApplicationWithExternalServiceProvider> AddApplicationAsync<TStartupModule>(
[NotNull] this IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
return await AbpApplicationFactory.CreateAsync<TStartupModule>(services, optionsAction);
}
public async static Task<IAbpApplicationWithExternalServiceProvider> AddApplicationAsync(
[NotNull] this IServiceCollection services,
[NotNull] Type startupModuleType,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
{
return await AbpApplicationFactory.CreateAsync(startupModuleType, services, optionsAction);
}
}

107
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -46,7 +47,21 @@ public abstract class AbpApplicationBase : IAbpApplication
services.AddCoreAbpServices(this, options);
Modules = LoadModules(services, options);
ConfigureServices();
if (!options.ManualConfigureServices)
{
ConfigureServices();
}
}
public virtual async Task ShutdownAsync()
{
using (var scope = ServiceProvider.CreateScope())
{
await scope.ServiceProvider
.GetRequiredService<IModuleManager>()
.ShutdownModulesAsync(new ApplicationShutdownContext(scope.ServiceProvider));
}
}
public virtual void Shutdown()
@ -70,6 +85,17 @@ public abstract class AbpApplicationBase : IAbpApplication
ServiceProvider.GetRequiredService<ObjectAccessor<IServiceProvider>>().Value = ServiceProvider;
}
protected virtual async Task InitializeModulesAsync()
{
using (var scope = ServiceProvider.CreateScope())
{
WriteInitLogs(scope.ServiceProvider);
await scope.ServiceProvider
.GetRequiredService<IModuleManager>()
.InitializeModulesAsync(new ApplicationInitializationContext(scope.ServiceProvider));
}
}
protected virtual void InitializeModules()
{
using (var scope = ServiceProvider.CreateScope())
@ -111,7 +137,84 @@ public abstract class AbpApplicationBase : IAbpApplication
}
//TODO: We can extract a new class for this
protected virtual void ConfigureServices()
public virtual async Task ConfigureServicesAsync()
{
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context);
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
abpModule.ServiceConfigurationContext = context;
}
}
//PreConfigureServices
foreach (var module in Modules.Where(m => m.Instance is IPreConfigureServices))
{
try
{
await ((IPreConfigureServices)module.Instance).PreConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
var assemblies = new HashSet<Assembly>();
//ConfigureServices
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
if (!abpModule.SkipAutoServiceRegistration)
{
var assembly = module.Type.Assembly;
if (!assemblies.Contains(assembly))
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
}
}
}
try
{
await module.Instance.ConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
//PostConfigureServices
foreach (var module in Modules.Where(m => m.Instance is IPostConfigureServices))
{
try
{
await ((IPostConfigureServices)module.Instance).PostConfigureServicesAsync(context);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServicesAsync)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
}
}
foreach (var module in Modules)
{
if (module.Instance is AbpModule abpModule)
{
abpModule.ServiceConfigurationContext = null;
}
}
}
//TODO: We can extract a new class for this
public virtual void ConfigureServices()
{
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context);

3
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationCreationOptions.cs

@ -19,10 +19,13 @@ public class AbpApplicationCreationOptions
[NotNull]
public AbpConfigurationBuilderOptions Configuration { get; }
public bool ManualConfigureServices { get; set; }
public AbpApplicationCreationOptions([NotNull] IServiceCollection services)
{
Services = Check.NotNull(services, nameof(services));
PlugInSources = new PlugInSourceList();
Configuration = new AbpConfigurationBuilderOptions();
ManualConfigureServices = false;
}
}

55
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationFactory.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
@ -7,6 +8,60 @@ namespace Volo.Abp;
public static class AbpApplicationFactory
{
public async static Task<IAbpApplicationWithInternalServiceProvider> CreateAsync<TStartupModule>(
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
var app = Create(typeof(TStartupModule), options =>
{
optionsAction?.Invoke(options);
options.ManualConfigureServices = true;
});
await app.ConfigureServicesAsync();
return app;
}
public async static Task<IAbpApplicationWithInternalServiceProvider> CreateAsync(
[NotNull] Type startupModuleType,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
{
var app = new AbpApplicationWithInternalServiceProvider(startupModuleType, options =>
{
optionsAction?.Invoke(options);
options.ManualConfigureServices = true;
});
await app.ConfigureServicesAsync();
return app;
}
public async static Task<IAbpApplicationWithExternalServiceProvider> CreateAsync<TStartupModule>(
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
var app = Create(typeof(TStartupModule), services, options =>
{
optionsAction?.Invoke(options);
options.ManualConfigureServices = true;
});
await app.ConfigureServicesAsync();
return app;
}
public async static Task<IAbpApplicationWithExternalServiceProvider> CreateAsync(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
{
var app = new AbpApplicationWithExternalServiceProvider(startupModuleType, services, options =>
{
optionsAction?.Invoke(options);
options.ManualConfigureServices = true;
});
await app.ConfigureServicesAsync();
return app;
}
public static IAbpApplicationWithInternalServiceProvider Create<TStartupModule>(
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule

10
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
@ -35,6 +36,15 @@ internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase, I
SetServiceProvider(serviceProvider);
}
public async Task InitializeAsync(IServiceProvider serviceProvider)
{
Check.NotNull(serviceProvider, nameof(serviceProvider));
SetServiceProvider(serviceProvider);
await InitializeModulesAsync();
}
public void Initialize([NotNull] IServiceProvider serviceProvider)
{
Check.NotNull(serviceProvider, nameof(serviceProvider));

7
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
@ -44,6 +45,12 @@ internal class AbpApplicationWithInternalServiceProvider : AbpApplicationBase, I
return ServiceProvider;
}
public async Task InitializeAsync()
{
CreateServiceProvider();
await InitializeModulesAsync();
}
public void Initialize()
{
CreateServiceProvider();

6
framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplication.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
@ -23,6 +24,11 @@ public interface IAbpApplication : IModuleContainer, IDisposable
/// </summary>
IServiceProvider ServiceProvider { get; }
/// <summary>
/// Used to gracefully shutdown the application and all modules.
/// </summary>
Task ShutdownAsync();
/// <summary>
/// Used to gracefully shutdown the application and all modules.
/// </summary>

13
framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp;
@ -10,6 +11,18 @@ public interface IAbpApplicationWithExternalServiceProvider : IAbpApplication
/// </summary>
void SetServiceProvider([NotNull] IServiceProvider serviceProvider);
/// <summary>
/// Call the Pre/Post/ConfigureServicesAsync method of the modules.
/// </summary>
Task ConfigureServicesAsync();
/// <summary>
/// Sets the service provider and initializes all the modules.
/// If <see cref="SetServiceProvider"/> was called before, the same
/// <see cref="serviceProvider"/> instance should be passed to this method.
/// </summary>
Task InitializeAsync([NotNull] IServiceProvider serviceProvider);
/// <summary>
/// Sets the service provider and initializes all the modules.
/// If <see cref="SetServiceProvider"/> was called before, the same

13
framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp;
@ -10,6 +11,18 @@ public interface IAbpApplicationWithInternalServiceProvider : IAbpApplication
/// </summary>
IServiceProvider CreateServiceProvider();
/// <summary>
/// Call the Pre/Post/ConfigureServicesAsync method of the modules.
/// </summary>
Task ConfigureServicesAsync();
/// <summary>
/// Creates the service provider and initializes all the modules.
/// If <see cref="CreateServiceProvider"/> method was called before,
/// it does not re-create it, but uses the previous one.
/// </summary>
Task InitializeAsync();
/// <summary>
/// Creates the service provider and initializes all the modules.
/// If <see cref="CreateServiceProvider"/> method was called before,

5
framework/src/Volo.Abp.Core/Volo/Abp/IOnApplicationInitialization.cs

@ -1,8 +1,11 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp;
public interface IOnApplicationInitialization
{
Task OnApplicationInitializationAsync([NotNull] ApplicationInitializationContext context);
void OnApplicationInitialization([NotNull] ApplicationInitializationContext context);
}

5
framework/src/Volo.Abp.Core/Volo/Abp/IOnApplicationShutdown.cs

@ -1,8 +1,11 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp;
public interface IOnApplicationShutdown
{
Task OnApplicationShutdownAsync([NotNull] ApplicationShutdownContext context);
void OnApplicationShutdown([NotNull] ApplicationShutdownContext context);
}

43
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModule.cs

@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -30,36 +31,78 @@ public abstract class AbpModule :
private ServiceConfigurationContext _serviceConfigurationContext;
public virtual Task PreConfigureServicesAsync(ServiceConfigurationContext context)
{
PreConfigureServices(context);
return Task.CompletedTask;
}
public virtual void PreConfigureServices(ServiceConfigurationContext context)
{
}
public virtual Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
ConfigureServices(context);
return Task.CompletedTask;
}
public virtual void ConfigureServices(ServiceConfigurationContext context)
{
}
public virtual Task PostConfigureServicesAsync(ServiceConfigurationContext context)
{
PostConfigureServices(context);
return Task.CompletedTask;
}
public virtual void PostConfigureServices(ServiceConfigurationContext context)
{
}
public virtual Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnPreApplicationInitialization(context);
return Task.CompletedTask;
}
public virtual void OnPreApplicationInitialization(ApplicationInitializationContext context)
{
}
public virtual Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnApplicationInitialization(context);
return Task.CompletedTask;
}
public virtual void OnApplicationInitialization(ApplicationInitializationContext context)
{
}
public virtual Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnPostApplicationInitialization(context);
return Task.CompletedTask;
}
public virtual void OnPostApplicationInitialization(ApplicationInitializationContext context)
{
}
public virtual Task OnApplicationShutdownAsync(ApplicationShutdownContext context)
{
OnApplicationShutdown(context);
return Task.CompletedTask;
}
public virtual void OnApplicationShutdown(ApplicationShutdownContext context)
{

36
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DefaultModuleLifecycleContributor.cs

@ -1,7 +1,17 @@
namespace Volo.Abp.Modularity;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public class OnApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnApplicationInitialization onApplicationInitialization)
{
await onApplicationInitialization.OnApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnApplicationInitialization)?.OnApplicationInitialization(context);
@ -10,6 +20,14 @@ public class OnApplicationInitializationModuleLifecycleContributor : ModuleLifec
public class OnApplicationShutdownModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task ShutdownAsync(ApplicationShutdownContext context, IAbpModule module)
{
if (module is IOnApplicationShutdown onApplicationShutdown)
{
await onApplicationShutdown.OnApplicationShutdownAsync(context);
}
}
public override void Shutdown(ApplicationShutdownContext context, IAbpModule module)
{
(module as IOnApplicationShutdown)?.OnApplicationShutdown(context);
@ -18,6 +36,14 @@ public class OnApplicationShutdownModuleLifecycleContributor : ModuleLifecycleCo
public class OnPreApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnPreApplicationInitialization onPreApplicationInitialization)
{
await onPreApplicationInitialization.OnPreApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnPreApplicationInitialization)?.OnPreApplicationInitialization(context);
@ -26,6 +52,14 @@ public class OnPreApplicationInitializationModuleLifecycleContributor : ModuleLi
public class OnPostApplicationInitializationModuleLifecycleContributor : ModuleLifecycleContributorBase
{
public async override Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
if (module is IOnPostApplicationInitialization onPostApplicationInitialization)
{
await onPostApplicationInitialization.OnPostApplicationInitializationAsync(context);
}
}
public override void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
(module as IOnPostApplicationInitialization)?.OnPostApplicationInitialization(context);

6
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs

@ -1,6 +1,10 @@
namespace Volo.Abp.Modularity;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public interface IAbpModule
{
Task ConfigureServicesAsync(ServiceConfigurationContext context);
void ConfigureServices(ServiceConfigurationContext context);
}

7
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IModuleLifecycleContributor.cs

@ -1,11 +1,16 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Modularity;
public interface IModuleLifecycleContributor : ITransientDependency
{
Task InitializeAsync([NotNull] ApplicationInitializationContext context, [NotNull] IAbpModule module);
void Initialize([NotNull] ApplicationInitializationContext context, [NotNull] IAbpModule module);
Task ShutdownAsync([NotNull] ApplicationShutdownContext context, [NotNull] IAbpModule module);
void Shutdown([NotNull] ApplicationShutdownContext context, [NotNull] IAbpModule module);
}

7
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IModuleManager.cs

@ -1,10 +1,15 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Modularity;
public interface IModuleManager
{
Task InitializeModulesAsync([NotNull] ApplicationInitializationContext context);
void InitializeModules([NotNull] ApplicationInitializationContext context);
Task ShutdownModulesAsync([NotNull] ApplicationShutdownContext context);
void ShutdownModules([NotNull] ApplicationShutdownContext context);
}

5
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IOnPostApplicationInitialization.cs

@ -1,8 +1,11 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Modularity;
public interface IOnPostApplicationInitialization
{
Task OnPostApplicationInitializationAsync([NotNull] ApplicationInitializationContext context);
void OnPostApplicationInitialization([NotNull] ApplicationInitializationContext context);
}

5
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IOnPreApplicationInitialization.cs

@ -1,8 +1,11 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Modularity;
public interface IOnPreApplicationInitialization
{
Task OnPreApplicationInitializationAsync([NotNull] ApplicationInitializationContext context);
void OnPreApplicationInitialization([NotNull] ApplicationInitializationContext context);
}

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IPostConfigureServices.cs

@ -1,8 +1,10 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public interface IPostConfigureServices
{
Task PostConfigureServicesAsync(ServiceConfigurationContext context);
void PostConfigureServices(ServiceConfigurationContext context);
}

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IPreConfigureServices.cs

@ -1,8 +1,10 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public interface IPreConfigureServices
{
Task PreConfigureServicesAsync(ServiceConfigurationContext context);
void PreConfigureServices(ServiceConfigurationContext context);
}

14
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLifecycleContributorBase.cs

@ -1,11 +1,23 @@
namespace Volo.Abp.Modularity;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public abstract class ModuleLifecycleContributorBase : IModuleLifecycleContributor
{
public virtual Task InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
{
return Task.CompletedTask;
}
public virtual void Initialize(ApplicationInitializationContext context, IAbpModule module)
{
}
public virtual Task ShutdownAsync(ApplicationShutdownContext context, IAbpModule module)
{
return Task.CompletedTask;
}
public virtual void Shutdown(ApplicationShutdownContext context, IAbpModule module)
{
}

41
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -30,6 +31,26 @@ public class ModuleManager : IModuleManager, ISingletonDependency
.ToArray();
}
public virtual async Task InitializeModulesAsync(ApplicationInitializationContext context)
{
foreach (var contributor in _lifecycleContributors)
{
foreach (var module in _moduleContainer.Modules)
{
try
{
await contributor.InitializeAsync(context, module.Instance);
}
catch (Exception ex)
{
throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex);
}
}
}
_logger.LogInformation("Initialized all ABP modules.");
}
public void InitializeModules(ApplicationInitializationContext context)
{
foreach (var contributor in _lifecycleContributors)
@ -50,6 +71,26 @@ public class ModuleManager : IModuleManager, ISingletonDependency
_logger.LogInformation("Initialized all ABP modules.");
}
public virtual async Task ShutdownModulesAsync(ApplicationShutdownContext context)
{
var modules = _moduleContainer.Modules.Reverse().ToList();
foreach (var contributor in _lifecycleContributors)
{
foreach (var module in modules)
{
try
{
await contributor.ShutdownAsync(context, module.Instance);
}
catch (Exception ex)
{
throw new AbpShutdownException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex);
}
}
}
}
public void ShutdownModules(ApplicationShutdownContext context)
{
var modules = _moduleContainer.Modules.Reverse().ToList();

82
framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
using Volo.Abp.Modularity.PlugIns;
@ -8,6 +9,39 @@ namespace Volo.Abp;
public class AbpApplication_Initialize_Tests
{
[Fact]
public async Task Should_Initialize_Single_Module_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>())
{
//Assert
var module = application.Services.GetSingletonInstance<IndependentEmptyModule>();
module.PreConfigureServicesAsyncIsCalled.ShouldBeTrue();
module.PreConfigureServicesIsCalled.ShouldBeTrue();
module.ConfigureServicesAsyncIsCalled.ShouldBeTrue();
module.ConfigureServicesIsCalled.ShouldBeTrue();
module.PostConfigureServicesAsyncIsCalled.ShouldBeTrue();
module.PostConfigureServicesIsCalled.ShouldBeTrue();
//Act
await application.InitializeAsync();
//Assert
application.ServiceProvider.GetRequiredService<IndependentEmptyModule>().ShouldBeSameAs(module);
module.OnApplicationInitializeAsyncIsCalled.ShouldBeTrue();
module.OnApplicationInitializeIsCalled.ShouldBeTrue();
//Act
await application.ShutdownAsync();
//Assert
module.OnApplicationShutdownAsyncIsCalled.ShouldBeTrue();
module.OnApplicationShutdownIsCalled.ShouldBeTrue();
}
}
[Fact]
public void Should_Initialize_Single_Module()
{
@ -34,6 +68,50 @@ public class AbpApplication_Initialize_Tests
}
}
[Fact]
public async Task Should_Initialize_PlugIn_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>(options =>
{
options.PlugInSources.AddTypes(typeof(IndependentEmptyPlugInModule));
}))
{
//Assert
var plugInModule = application.Services.GetSingletonInstance<IndependentEmptyPlugInModule>();
plugInModule.PreConfigureServicesAsyncIsCalled.ShouldBeTrue();
plugInModule.PreConfigureServicesIsCalled.ShouldBeTrue();
plugInModule.ConfigureServicesAsyncIsCalled.ShouldBeTrue();
plugInModule.ConfigureServicesIsCalled.ShouldBeTrue();
plugInModule.PostConfigureServicesAsyncIsCalled.ShouldBeTrue();
plugInModule.PostConfigureServicesIsCalled.ShouldBeTrue();
//Act
await application.InitializeAsync();
//Assert
application.ServiceProvider.GetRequiredService<IndependentEmptyPlugInModule>().ShouldBeSameAs(plugInModule);
plugInModule.OnPreApplicationInitializationAsyncIsCalled.ShouldBeTrue();
plugInModule.OnPreApplicationInitializationIsCalled.ShouldBeTrue();
plugInModule.OnApplicationInitializeAsyncIsCalled.ShouldBeTrue();
plugInModule.OnApplicationInitializeIsCalled.ShouldBeTrue();
plugInModule.OnPostApplicationInitializationAsyncIsCalled.ShouldBeTrue();
plugInModule.OnPostApplicationInitializationIsCalled.ShouldBeTrue();
//Act
await application.ShutdownAsync();
//Assert
plugInModule.OnApplicationShutdownAsyncIsCalled.ShouldBeTrue();
plugInModule.OnApplicationShutdownIsCalled.ShouldBeTrue();
}
}
[Fact]
public void Should_Initialize_PlugIn()
{
@ -53,7 +131,9 @@ public class AbpApplication_Initialize_Tests
//Assert
application.ServiceProvider.GetRequiredService<IndependentEmptyPlugInModule>().ShouldBeSameAs(plugInModule);
plugInModule.OnPreApplicationInitializationIsCalled.ShouldBeTrue();
plugInModule.OnApplicationInitializeIsCalled.ShouldBeTrue();
plugInModule.OnPostApplicationInitializationIsCalled.ShouldBeTrue();
//Act
application.Shutdown();

36
framework/test/Volo.Abp.Core.Tests/Volo/Abp/Configuration/ConfigurationAccessor_Tests.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.Configuration;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
@ -8,6 +9,22 @@ namespace Volo.Abp.Configuration;
public class ConfigurationAccessor_Tests
{
[Fact]
public async Task Should_Use_Empty_ConfigurationRoot_By_Default_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>())
{
var configuration1 = application.Services.GetConfiguration();
configuration1.ShouldNotBeNull();
await application.InitializeAsync();
var configuration2 = ResolveConfiguration(application);
configuration2.ShouldBe(configuration1);
}
}
[Fact]
public void Should_Use_Empty_ConfigurationRoot_By_Default()
{
@ -24,6 +41,23 @@ public class ConfigurationAccessor_Tests
}
}
[Fact]
public async Task Should_Use_The_Registered_ConfigurationRoot_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>())
{
var myConfiguration = new ConfigurationBuilder().Build();
application.Services.ReplaceConfiguration(myConfiguration);
application.Services.GetConfiguration().ShouldBe(myConfiguration);
await application.InitializeAsync();
var configuration = ResolveConfiguration(application);
configuration.ShouldBe(myConfiguration);
}
}
[Fact]
public void Should_Use_The_Registered_ConfigurationRoot()
{

15
framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AutoServiceRegistration_Tests.cs

@ -1,4 +1,5 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
@ -8,6 +9,20 @@ namespace Volo.Abp.DependencyInjection;
public class AutoServiceRegistration_Tests
{
[Fact]
public async Task AutoServiceRegistration_Should_Not_Duplicate_Test_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<TestModule>())
{
//Act
await application.InitializeAsync();
//Assert
var services = application.ServiceProvider.GetServices<TestService>().ToList();
services.Count.ShouldBe(1);
}
}
[Fact]
public void AutoServiceRegistration_Should_Not_Duplicate_Test()
{

31
framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/HybridServiceScopeFactory_Tests.cs

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
@ -8,6 +9,26 @@ namespace Volo.Abp.DependencyInjection;
public class HybridServiceScopeFactory_Tests
{
[Fact]
public async Task Should_Use_Default_ServiceScopeFactory_By_Default_Async()
{
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>())
{
application.Services.AddType(typeof(MyServiceAsync));
await application.InitializeAsync();
var serviceScopeFactory = application.ServiceProvider.GetRequiredService<IHybridServiceScopeFactory>();
using (var scope = serviceScopeFactory.CreateScope())
{
scope.ServiceProvider.GetRequiredService<MyServiceAsync>();
}
MyServiceAsync.DisposeCount.ShouldBe(1);
}
}
[Fact]
public void Should_Use_Default_ServiceScopeFactory_By_Default()
{
@ -28,6 +49,16 @@ public class HybridServiceScopeFactory_Tests
}
}
private class MyServiceAsync : ITransientDependency, IDisposable
{
public static int DisposeCount { get; private set; }
public void Dispose()
{
++DisposeCount;
}
}
private class MyService : ITransientDependency, IDisposable
{
public static int DisposeCount { get; private set; }

68
framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/TestModuleBase.cs

@ -1,39 +1,97 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
namespace Volo.Abp.Modularity;
public class TestModuleBase : AbpModule
{
public bool PreConfigureServicesIsCalled { get; set; }
public bool PreConfigureServicesAsyncIsCalled { get; set; }
public bool ConfigureServicesAsyncIsCalled { get; set; }
public bool PostConfigureServicesAsyncIsCalled { get; set; }
public bool OnPreApplicationInitializationIsCalled { get; set; }
public bool OnPostApplicationInitializationIsCalled { get; set; }
public bool OnApplicationInitializeAsyncIsCalled { get; set; }
public bool OnApplicationShutdownAsyncIsCalled { get; set; }
public bool PreConfigureServicesIsCalled { get; set; }
public bool ConfigureServicesIsCalled { get; set; }
public bool PostConfigureServicesIsCalled { get; set; }
public bool OnPreApplicationInitializationAsyncIsCalled { get; set; }
public bool OnPostApplicationInitializationAsyncIsCalled { get; set; }
public bool OnApplicationInitializeIsCalled { get; set; }
public bool OnApplicationShutdownIsCalled { get; set; }
public override Task PreConfigureServicesAsync(ServiceConfigurationContext context)
{
PreConfigureServicesAsyncIsCalled = true;
return base.PreConfigureServicesAsync(context);
}
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigureServicesIsCalled = true;
}
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
ConfigureServicesAsyncIsCalled = true;
return base.ConfigureServicesAsync(context);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
ConfigureServicesIsCalled = true;
}
public override Task PostConfigureServicesAsync(ServiceConfigurationContext context)
{
PostConfigureServicesAsyncIsCalled = true;
return base.PostConfigureServicesAsync(context);
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{
PostConfigureServicesIsCalled = true;
}
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnPreApplicationInitializationAsyncIsCalled = true;
return base.OnPreApplicationInitializationAsync(context);
}
public override void OnPreApplicationInitialization(ApplicationInitializationContext context)
{
OnPreApplicationInitializationIsCalled = true;
}
public override Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnPostApplicationInitializationAsyncIsCalled = true;
return base.OnPostApplicationInitializationAsync(context);
}
public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
{
OnPostApplicationInitializationIsCalled = true;
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
OnApplicationInitializeAsyncIsCalled = true;
return base.OnApplicationInitializationAsync(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
OnApplicationInitializeIsCalled = true;
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)
{
OnApplicationShutdownAsyncIsCalled = true;
return base.OnApplicationShutdownAsync(context);
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
OnApplicationShutdownIsCalled = true;

Loading…
Cancel
Save