mirror of https://github.com/abpframework/abp.git
19 changed files with 386 additions and 115 deletions
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
@ -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<Type> FindAllModuleTypes(Type startupModuleType) |
|||
{ |
|||
var moduleTypes = new List<Type>(); |
|||
AddModuleAndDependenciesResursively(moduleTypes, startupModuleType); |
|||
moduleTypes.AddIfNotContains(typeof(AbpKernelModule)); |
|||
return moduleTypes; |
|||
} |
|||
|
|||
public static List<Type> FindDependedModuleTypes(Type moduleType) |
|||
{ |
|||
AbpModule.CheckAbpModuleType(moduleType); |
|||
|
|||
var dependencies = new List<Type>(); |
|||
|
|||
var dependencyDescriptors = moduleType |
|||
.GetTypeInfo() |
|||
.GetCustomAttributes() |
|||
.OfType<IDependedModuleTypesProvider>(); |
|||
|
|||
foreach (var descriptor in dependencyDescriptors) |
|||
{ |
|||
foreach (var dependedModuleType in descriptor.GetDependedModuleTypes()) |
|||
{ |
|||
dependencies.AddIfNotContains(dependedModuleType); |
|||
} |
|||
} |
|||
|
|||
return dependencies; |
|||
} |
|||
|
|||
private static void AddModuleAndDependenciesResursively(List<Type> moduleTypes, Type moduleType) |
|||
{ |
|||
AbpModule.CheckAbpModuleType(moduleType); |
|||
|
|||
if (moduleTypes.Contains(moduleType)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
moduleTypes.Add(moduleType); |
|||
|
|||
foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) |
|||
{ |
|||
AddModuleAndDependenciesResursively(moduleTypes, dependedModuleType); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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<Type> GetModules() |
|||
{ |
|||
var modules = new List<Type>(); |
|||
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Modularity.PlugIns |
|||
{ |
|||
public interface IPlugInSource |
|||
{ |
|||
List<Type> GetModules(); |
|||
} |
|||
} |
|||
@ -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<Type> GetModulesWithAllDependencies(this IPlugInSource plugInSource) |
|||
{ |
|||
return plugInSource |
|||
.GetModules() |
|||
.SelectMany(AbpModuleFinder.FindAllModuleTypes) |
|||
.Distinct() |
|||
.ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace Volo.Abp.Modularity.PlugIns |
|||
{ |
|||
public class PlugInSourceList : List<IPlugInSource> |
|||
{ |
|||
internal List<Type> GetAllModules() |
|||
{ |
|||
return this |
|||
.SelectMany(pluginSource => pluginSource.GetModulesWithAllDependencies()) |
|||
.Distinct() |
|||
.ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -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)); |
|||
} |
|||
} |
|||
} |
|||
@ -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<Type> GetModules() |
|||
{ |
|||
return _moduleTypes.ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -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<Assembly> 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(); |
|||
} |
|||
} |
|||
} |
|||
@ -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<IndependentEmptyModule>(services)) |
|||
{ |
|||
//Act
|
|||
|
|||
application.Initialize(services.BuildServiceProvider()); |
|||
|
|||
//Assert
|
|||
|
|||
var module = application.ServiceProvider.GetRequiredService<IndependentEmptyModule>(); |
|||
module.ConfigureServicesIsCalled.ShouldBeTrue(); |
|||
module.OnApplicationInitializeIsCalled.ShouldBeTrue(); |
|||
} |
|||
} |
|||
} |
|||
@ -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<IndependentEmptyModule>(services)) |
|||
{ |
|||
//Act
|
|||
|
|||
application.Initialize(services.BuildServiceProvider()); |
|||
|
|||
//Assert
|
|||
|
|||
var module = application.ServiceProvider.GetRequiredService<IndependentEmptyModule>(); |
|||
module.ConfigureServicesIsCalled.ShouldBeTrue(); |
|||
module.OnApplicationInitializeIsCalled.ShouldBeTrue(); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Initialize_PlugIn() |
|||
{ |
|||
//Arrange
|
|||
|
|||
var services = new ServiceCollection(); |
|||
|
|||
using (var application = AbpApplication.Create<IndependentEmptyModule>(services, options => |
|||
{ |
|||
options.PlugInSources.AddTypes(typeof(IndependentEmptyPlugInModule)); |
|||
})) |
|||
{ |
|||
//Act
|
|||
|
|||
application.Initialize(services.BuildServiceProvider()); |
|||
|
|||
//Assert
|
|||
|
|||
var plugInModule = application.ServiceProvider.GetRequiredService<IndependentEmptyPlugInModule>(); |
|||
plugInModule.ConfigureServicesIsCalled.ShouldBeTrue(); |
|||
plugInModule.OnApplicationInitializeIsCalled.ShouldBeTrue(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue