From aa6c0461f65d7b8435ba9f08c9b50a21030606af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Sun, 11 Dec 2016 21:34:54 +0300 Subject: [PATCH] Load plugins modules. --- src/Volo.Abp/Volo/Abp/AbpApplication.cs | 38 ++++++-- .../Volo/Abp/AbpApplicationOptions.cs | 14 +++ src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs | 23 ++++- .../Abp/Modularity/AbpModuleDescriptor.cs | 8 +- .../Volo/Abp/Modularity/AbpModuleFinder.cs | 58 ++++++++++++ .../Volo/Abp/Modularity/IModuleLoader.cs | 3 +- .../Volo/Abp/Modularity/ModuleLoader.cs | 92 ++++--------------- .../Modularity/PlugIns/FolderPlugInSource.cs | 47 ++++++++++ .../Abp/Modularity/PlugIns/IPlugInSource.cs | 10 ++ .../PlugIns/PlugInSourceExtensions.cs | 18 ++++ .../Modularity/PlugIns/PlugInSourceList.cs | 17 ++++ .../PlugIns/PlugInSourceListExtensions.cs | 18 ++++ .../PlugIns/PlugInTypeListSource.cs | 21 +++++ .../Volo/Abp/Reflection/AssemblyHelper.cs | 22 +++++ src/Volo.Abp/project.json | 3 +- test/Volo.Abp.Tests/AbpApplication_Tests.cs | 29 ------ .../Abp/AbpApplication_Initialize_Tests.cs | 56 +++++++++++ .../IndependentEmptyPlugInModule.cs | 21 +++++ .../Volo/Abp/Modularity/ModuleLoader_Tests.cs | 3 +- 19 files changed, 386 insertions(+), 115 deletions(-) create mode 100644 src/Volo.Abp/Volo/Abp/AbpApplicationOptions.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/AbpModuleFinder.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/FolderPlugInSource.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/IPlugInSource.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceExtensions.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceList.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceListExtensions.cs create mode 100644 src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInTypeListSource.cs create mode 100644 src/Volo.Abp/Volo/Abp/Reflection/AssemblyHelper.cs delete mode 100644 test/Volo.Abp.Tests/AbpApplication_Tests.cs create mode 100644 test/Volo.Abp.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs create mode 100644 test/Volo.Abp.Tests/Volo/Abp/Modularity/IndependentEmptyPlugInModule.cs diff --git a/src/Volo.Abp/Volo/Abp/AbpApplication.cs b/src/Volo.Abp/Volo/Abp/AbpApplication.cs index cb33119d3a..5b4386c2ea 100644 --- a/src/Volo.Abp/Volo/Abp/AbpApplication.cs +++ b/src/Volo.Abp/Volo/Abp/AbpApplication.cs @@ -1,4 +1,5 @@ using System; +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; @@ -10,20 +11,32 @@ namespace Volo.Abp public IServiceProvider ServiceProvider { get; private set; } - private AbpApplication(Type startupModuleType, IServiceCollection services) + private AbpApplication(Type startupModuleType, IServiceCollection services, Action optionsAction) { StartupModuleType = startupModuleType; - - services.AddSingleton(this); - services.AddCoreAbpServices(); - services.GetSingletonInstance().LoadAll(services, StartupModuleType); + var options = new AbpApplicationOptions(); + + optionsAction?.Invoke(options); + + AddServices(services); + LoadModules(services, options); } - public static AbpApplication Create(IServiceCollection services) + public static AbpApplication Create([NotNull] IServiceCollection services) where TStartupModule : IAbpModule { - return new AbpApplication(typeof(TStartupModule), services); + return Create(services, null); + } + + public static AbpApplication Create( + [NotNull] IServiceCollection services, + [CanBeNull] Action optionsAction) + where TStartupModule : IAbpModule + { + Check.NotNull(services, nameof(services)); + + return new AbpApplication(typeof(TStartupModule), services, optionsAction); } public void Initialize(IServiceProvider serviceProvider) @@ -32,6 +45,17 @@ namespace Volo.Abp ServiceProvider.GetRequiredService().Initialize(); } + private void AddServices(IServiceCollection services) + { + services.AddSingleton(this); + services.AddCoreAbpServices(); + } + + private void LoadModules(IServiceCollection services, AbpApplicationOptions options) + { + services.GetSingletonInstance().LoadAll(services, StartupModuleType, options.PlugInSources); + } + public void Dispose() { diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationOptions.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationOptions.cs new file mode 100644 index 0000000000..ed8260fc8c --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/AbpApplicationOptions.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Modularity.PlugIns; + +namespace Volo.Abp +{ + public class AbpApplicationOptions + { + public PlugInSourceList PlugInSources { get; set; } + + public AbpApplicationOptions() + { + PlugInSources = new PlugInSourceList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs b/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs index 8069ba28a8..4270b6ae8f 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/AbpModule.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.Modularity { @@ -15,5 +17,24 @@ namespace Volo.Abp.Modularity { } + + public static bool IsAbpModule(Type type) + { + var typeInfo = type.GetTypeInfo(); + + return + typeInfo.IsClass && + !typeInfo.IsAbstract && + !typeInfo.IsGenericType && + typeof(IAbpModule).GetTypeInfo().IsAssignableFrom(type); + } + + public static void CheckAbpModuleType(Type moduleType) + { + if (!IsAbpModule(moduleType)) + { + throw new ArgumentException("Given type is not an ABP module: " + moduleType.AssemblyQualifiedName); + } + } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs index 5d37a81604..0bf04605a0 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using JetBrains.Annotations; namespace Volo.Abp.Modularity @@ -10,13 +11,18 @@ namespace Volo.Abp.Modularity public IAbpModule Instance { get; } - public List Dependencies { get; } + internal List Dependencies { get; } public AbpModuleDescriptor([NotNull] Type type, [NotNull] IAbpModule instance) { Check.NotNull(type, nameof(type)); Check.NotNull(instance, nameof(instance)); + if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType())) + { + throw new ArgumentException($"Given module instance ({instance.GetType().AssemblyQualifiedName}) is not an instance of given module type: {type.AssemblyQualifiedName}"); + } + Type = type; Instance = instance; diff --git a/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleFinder.cs b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleFinder.cs new file mode 100644 index 0000000000..1a159995f8 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleFinder.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Volo.ExtensionMethods.Collections.Generic; + +namespace Volo.Abp.Modularity +{ + public static class AbpModuleFinder + { + public static List FindAllModuleTypes(Type startupModuleType) + { + var moduleTypes = new List(); + AddModuleAndDependenciesResursively(moduleTypes, startupModuleType); + moduleTypes.AddIfNotContains(typeof(AbpKernelModule)); + return moduleTypes; + } + + public static List FindDependedModuleTypes(Type moduleType) + { + AbpModule.CheckAbpModuleType(moduleType); + + var dependencies = new List(); + + var dependencyDescriptors = moduleType + .GetTypeInfo() + .GetCustomAttributes() + .OfType(); + + foreach (var descriptor in dependencyDescriptors) + { + foreach (var dependedModuleType in descriptor.GetDependedModuleTypes()) + { + dependencies.AddIfNotContains(dependedModuleType); + } + } + + return dependencies; + } + + private static void AddModuleAndDependenciesResursively(List moduleTypes, Type moduleType) + { + AbpModule.CheckAbpModuleType(moduleType); + + if (moduleTypes.Contains(moduleType)) + { + return; + } + + moduleTypes.Add(moduleType); + + foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) + { + AddModuleAndDependenciesResursively(moduleTypes, dependedModuleType); + } + } + } +} diff --git a/src/Volo.Abp/Volo/Abp/Modularity/IModuleLoader.cs b/src/Volo.Abp/Volo/Abp/Modularity/IModuleLoader.cs index 53dc007713..e7075942ea 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/IModuleLoader.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/IModuleLoader.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity.PlugIns; namespace Volo.Abp.Modularity { @@ -8,6 +9,6 @@ namespace Volo.Abp.Modularity { IReadOnlyList Modules { get; } - void LoadAll(IServiceCollection services, Type startupModuleType); + void LoadAll(IServiceCollection services, Type startupModuleType, PlugInSourceList plugInSources); } } diff --git a/src/Volo.Abp/Volo/Abp/Modularity/ModuleLoader.cs b/src/Volo.Abp/Volo/Abp/Modularity/ModuleLoader.cs index 5a3fe1c9cb..698c957c65 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/ModuleLoader.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/ModuleLoader.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Reflection; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity.PlugIns; using Volo.ExtensionMethods.Collections.Generic; namespace Volo.Abp.Modularity @@ -18,22 +18,32 @@ namespace Volo.Abp.Modularity _modules = new List(); } - public virtual void LoadAll(IServiceCollection services, Type startupModuleType) + public virtual void LoadAll(IServiceCollection services, Type startupModuleType, PlugInSourceList plugInSources) { if (_modules.Any()) { throw new InvalidOperationException($"{nameof(LoadAll)} should be called only once!"); } - FillModules(services, startupModuleType); + FillModules(services, startupModuleType, plugInSources); SetModuleDependencies(); SortByDependency(startupModuleType); ConfigureServices(services); } - private void FillModules(IServiceCollection services, Type startupModuleType) + private void FillModules(IServiceCollection services, Type startupModuleType, PlugInSourceList plugInSources) { - foreach (var moduleType in FindAllModuleTypes(startupModuleType).Distinct()) + //All modules starting from the startup module + var moduleTypes = AbpModuleFinder.FindAllModuleTypes(startupModuleType); + + //Add plugin modules + foreach (var moduleType in plugInSources.GetAllModules()) + { + moduleTypes.AddIfNotContains(moduleType); + } + + //Create all modules + foreach (var moduleType in moduleTypes) { _modules.Add(CreateModuleDescriptor(services, moduleType)); } @@ -54,20 +64,12 @@ namespace Volo.Abp.Modularity _modules.MoveItem(m => m.Type == startupModuleType, _modules.Count - 1); } - protected virtual IEnumerable FindAllModuleTypes(Type startupModuleType) - { - var moduleTypes = new List(); - AddModuleAndDependenciesResursively(moduleTypes, startupModuleType); - moduleTypes.AddIfNotContains(typeof(AbpKernelModule)); - return moduleTypes; - } - protected virtual AbpModuleDescriptor CreateModuleDescriptor(IServiceCollection services, Type moduleType) { return new AbpModuleDescriptor(moduleType, CreateAndRegisterModule(services, moduleType)); } - private IAbpModule CreateAndRegisterModule(IServiceCollection services, Type moduleType) + protected virtual IAbpModule CreateAndRegisterModule(IServiceCollection services, Type moduleType) { var module = (IAbpModule) Activator.CreateInstance(moduleType); services.AddSingleton(moduleType, module); @@ -81,49 +83,10 @@ namespace Volo.Abp.Modularity module.Instance.ConfigureServices(services); } } - - protected virtual void AddModuleAndDependenciesResursively(List moduleTypes, Type moduleType) - { - CheckAbpModuleType(moduleType); - - if (moduleTypes.Contains(moduleType)) - { - return; - } - - moduleTypes.Add(moduleType); - - foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) - { - AddModuleAndDependenciesResursively(moduleTypes, dependedModuleType); - } - } - - protected virtual List FindDependedModuleTypes(Type moduleType) - { - CheckAbpModuleType(moduleType); - - var dependencies = new List(); - - var dependencyDescriptors = moduleType - .GetTypeInfo() - .GetCustomAttributes() - .OfType(); - - foreach (var descriptor in dependencyDescriptors) - { - foreach (var dependedModuleType in descriptor.GetDependedModuleTypes()) - { - dependencies.AddIfNotContains(dependedModuleType); - } - } - - return dependencies; - } - + protected virtual void SetModuleDependencies(AbpModuleDescriptor module) { - foreach (var dependedModuleType in FindDependedModuleTypes(module.Type)) + foreach (var dependedModuleType in AbpModuleFinder.FindDependedModuleTypes(module.Type)) { var dependedModule = _modules.FirstOrDefault(m => m.Type == dependedModuleType); if (dependedModule == null) @@ -134,24 +97,5 @@ namespace Volo.Abp.Modularity module.Dependencies.AddIfNotContains(dependedModule); } } - - protected static void CheckAbpModuleType(Type moduleType) - { - if (!IsAbpModule(moduleType)) - { - throw new ArgumentException("Given type is not an ABP module: " + moduleType.AssemblyQualifiedName); - } - } - - protected static bool IsAbpModule(Type type) - { - var typeInfo = type.GetTypeInfo(); - - return - typeInfo.IsClass && - !typeInfo.IsAbstract && - !typeInfo.IsGenericType && - typeof(IAbpModule).GetTypeInfo().IsAssignableFrom(type); - } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/FolderPlugInSource.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/FolderPlugInSource.cs new file mode 100644 index 0000000000..101cd1bff0 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/FolderPlugInSource.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Volo.Abp.Reflection; +using Volo.ExtensionMethods.Collections.Generic; + +namespace Volo.Abp.Modularity.PlugIns +{ + public class FolderPlugInSource : IPlugInSource + { + public string Folder { get; } + + public SearchOption SearchOption { get; set; } + + public FolderPlugInSource(string folder, SearchOption searchOption = SearchOption.TopDirectoryOnly) + { + Folder = folder; + SearchOption = searchOption; + } + + public List GetModules() + { + var modules = new List(); + + var assemblies = AssemblyHelper.GetAllAssembliesInFolder(Folder, SearchOption); + foreach (var assembly in assemblies) + { + try + { + foreach (var type in assembly.GetTypes()) + { + if (AbpModule.IsAbpModule(type)) + { + modules.AddIfNotContains(type); + } + } + } + catch (Exception ex) + { + throw new AbpException("Could not get module types from assembly: " + assembly.FullName, ex); + } + } + + return modules; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/IPlugInSource.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/IPlugInSource.cs new file mode 100644 index 0000000000..d5746e029c --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/IPlugInSource.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.Modularity.PlugIns +{ + public interface IPlugInSource + { + List GetModules(); + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceExtensions.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceExtensions.cs new file mode 100644 index 0000000000..d6c356eda6 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceExtensions.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Modularity.PlugIns +{ + public static class PlugInSourceExtensions + { + public static List GetModulesWithAllDependencies(this IPlugInSource plugInSource) + { + return plugInSource + .GetModules() + .SelectMany(AbpModuleFinder.FindAllModuleTypes) + .Distinct() + .ToList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceList.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceList.cs new file mode 100644 index 0000000000..6055298bd4 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceList.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Modularity.PlugIns +{ + public class PlugInSourceList : List + { + internal List GetAllModules() + { + return this + .SelectMany(pluginSource => pluginSource.GetModulesWithAllDependencies()) + .Distinct() + .ToList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceListExtensions.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceListExtensions.cs new file mode 100644 index 0000000000..c5387f16f5 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInSourceListExtensions.cs @@ -0,0 +1,18 @@ +using System; +using System.IO; + +namespace Volo.Abp.Modularity.PlugIns +{ + public static class PlugInSourceListExtensions + { + public static void AddFolder(this PlugInSourceList list, string folder, SearchOption searchOption = SearchOption.TopDirectoryOnly) + { + list.Add(new FolderPlugInSource(folder, searchOption)); + } + + public static void AddTypes(this PlugInSourceList list, params Type[] moduleTypes) + { + list.Add(new PlugInTypeListSource(moduleTypes)); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInTypeListSource.cs b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInTypeListSource.cs new file mode 100644 index 0000000000..ca09a6c306 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Modularity/PlugIns/PlugInTypeListSource.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Modularity.PlugIns +{ + public class PlugInTypeListSource : IPlugInSource + { + private readonly Type[] _moduleTypes; + + public PlugInTypeListSource(params Type[] moduleTypes) + { + _moduleTypes = moduleTypes; + } + + public List GetModules() + { + return _moduleTypes.ToList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Reflection/AssemblyHelper.cs b/src/Volo.Abp/Volo/Abp/Reflection/AssemblyHelper.cs new file mode 100644 index 0000000000..ed3c7cb54a --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Reflection/AssemblyHelper.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; + +namespace Volo.Abp.Reflection +{ + internal static class AssemblyHelper + { + public static List GetAllAssembliesInFolder(string folderPath, SearchOption searchOption) + { + var assemblyFiles = Directory + .EnumerateFiles(folderPath, "*.*", searchOption) + .Where(s => s.EndsWith(".dll") || s.EndsWith(".exe")); + + //TODO: AssemblyLoadContext not tested + + return assemblyFiles.Select(AssemblyLoadContext.Default.LoadFromAssemblyPath).ToList(); + } + } +} diff --git a/src/Volo.Abp/project.json b/src/Volo.Abp/project.json index de63af7468..3d3d725d50 100644 --- a/src/Volo.Abp/project.json +++ b/src/Volo.Abp/project.json @@ -7,7 +7,8 @@ "System.Collections.Immutable": "1.3.0", "Volo.ExtensionMethods": "1.0.0-*", "Newtonsoft.Json": "9.0.1", - "Nito.AsyncEx.Context": "1.1.0" + "Nito.AsyncEx.Context": "1.1.0", + "System.Runtime.Loader": "4.3.0" }, "frameworks": { diff --git a/test/Volo.Abp.Tests/AbpApplication_Tests.cs b/test/Volo.Abp.Tests/AbpApplication_Tests.cs deleted file mode 100644 index 12da9b7695..0000000000 --- a/test/Volo.Abp.Tests/AbpApplication_Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Shouldly; -using Volo.Abp; -using Volo.Abp.Modularity; -using Xunit; - -public class AbpApplication_Tests -{ - [Fact] - public void Should_Initialize_SingleModule_Application() - { - //Arrange - - var services = new ServiceCollection(); - - using (var application = AbpApplication.Create(services)) - { - //Act - - application.Initialize(services.BuildServiceProvider()); - - //Assert - - var module = application.ServiceProvider.GetRequiredService(); - module.ConfigureServicesIsCalled.ShouldBeTrue(); - module.OnApplicationInitializeIsCalled.ShouldBeTrue(); - } - } -} \ No newline at end of file diff --git a/test/Volo.Abp.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs b/test/Volo.Abp.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs new file mode 100644 index 0000000000..49aa3ef345 --- /dev/null +++ b/test/Volo.Abp.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs @@ -0,0 +1,56 @@ +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.Modularity.PlugIns; +using Xunit; + +namespace Volo.Abp +{ + public class AbpApplication_Initialize_Tests + { + [Fact] + public void Should_Initialize_Single_Module() + { + //Arrange + + var services = new ServiceCollection(); + + using (var application = AbpApplication.Create(services)) + { + //Act + + application.Initialize(services.BuildServiceProvider()); + + //Assert + + var module = application.ServiceProvider.GetRequiredService(); + module.ConfigureServicesIsCalled.ShouldBeTrue(); + module.OnApplicationInitializeIsCalled.ShouldBeTrue(); + } + } + + [Fact] + public void Should_Initialize_PlugIn() + { + //Arrange + + var services = new ServiceCollection(); + + using (var application = AbpApplication.Create(services, options => + { + options.PlugInSources.AddTypes(typeof(IndependentEmptyPlugInModule)); + })) + { + //Act + + application.Initialize(services.BuildServiceProvider()); + + //Assert + + var plugInModule = application.ServiceProvider.GetRequiredService(); + plugInModule.ConfigureServicesIsCalled.ShouldBeTrue(); + plugInModule.OnApplicationInitializeIsCalled.ShouldBeTrue(); + } + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Tests/Volo/Abp/Modularity/IndependentEmptyPlugInModule.cs b/test/Volo.Abp.Tests/Volo/Abp/Modularity/IndependentEmptyPlugInModule.cs new file mode 100644 index 0000000000..020c130cfe --- /dev/null +++ b/test/Volo.Abp.Tests/Volo/Abp/Modularity/IndependentEmptyPlugInModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.Modularity +{ + public class IndependentEmptyPlugInModule : AbpModule + { + public bool ConfigureServicesIsCalled { get; set; } + + public bool OnApplicationInitializeIsCalled { get; set; } + + public override void ConfigureServices(IServiceCollection services) + { + ConfigureServicesIsCalled = true; + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + OnApplicationInitializeIsCalled = true; + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs b/test/Volo.Abp.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs index 4452ccdbd8..dfa6a34ec4 100644 --- a/test/Volo.Abp.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs +++ b/test/Volo.Abp.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.Modularity.PlugIns; using Xunit; namespace Volo.Abp.Modularity @@ -10,7 +11,7 @@ namespace Volo.Abp.Modularity public void Should_Load_Modules_By_Dependency_Order() { var moduleLoader = new ModuleLoader(); - moduleLoader.LoadAll(new ServiceCollection(), typeof(MyStartupModule)); + moduleLoader.LoadAll(new ServiceCollection(), typeof(MyStartupModule), new PlugInSourceList()); moduleLoader.Modules.Count.ShouldBe(3); moduleLoader.Modules[0].Type.ShouldBe(typeof(AbpKernelModule)); moduleLoader.Modules[1].Type.ShouldBe(typeof(IndependentEmptyModule));