using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Abp.Collections.Extensions; using Abp.Configuration.Startup; using Abp.Dependency; using Abp.PlugIns; using Castle.Core.Logging; namespace Abp.Modules { /// /// This class is used to manage modules. /// public class AbpModuleManager : IAbpModuleManager { public AbpModuleInfo StartupModule { get; private set; } public IReadOnlyList Modules => _modules.ToImmutableList(); public ILogger Logger { get; set; } private AbpModuleCollection _modules; private readonly IIocManager _iocManager; private readonly IAbpPlugInManager _abpPlugInManager; public AbpModuleManager(IIocManager iocManager, IAbpPlugInManager abpPlugInManager) { _iocManager = iocManager; _abpPlugInManager = abpPlugInManager; Logger = NullLogger.Instance; } public virtual void Initialize(Type startupModule) { _modules = new AbpModuleCollection(startupModule); LoadAllModules(); } public virtual void StartModules() { var sortedModules = _modules.GetSortedModuleListByDependency(); sortedModules.ForEach(module => module.Instance.PreInitialize()); sortedModules.ForEach(module => module.Instance.Initialize()); sortedModules.ForEach(module => module.Instance.PostInitialize()); } public virtual void ShutdownModules() { Logger.Debug("Shutting down has been started"); var sortedModules = _modules.GetSortedModuleListByDependency(); sortedModules.Reverse(); sortedModules.ForEach(sm => sm.Instance.Shutdown()); Logger.Debug("Shutting down completed."); } private void LoadAllModules() { Logger.Debug("Loading Abp modules..."); List plugInModuleTypes; var moduleTypes = FindAllModuleTypes(out plugInModuleTypes).Distinct().ToList(); Logger.Debug("Found " + moduleTypes.Count + " ABP modules in total."); RegisterModules(moduleTypes); CreateModules(moduleTypes, plugInModuleTypes); _modules.EnsureKernelModuleToBeFirst(); _modules.EnsureStartupModuleToBeLast(); SetDependencies(); Logger.DebugFormat("{0} modules loaded.", _modules.Count); } private List FindAllModuleTypes(out List plugInModuleTypes) { plugInModuleTypes = new List(); var modules = AbpModule.FindDependedModuleTypesRecursivelyIncludingGivenModule(_modules.StartupModuleType); foreach (var plugInModuleType in _abpPlugInManager.PlugInSources.GetAllModules()) { if (modules.AddIfNotContains(plugInModuleType)) { plugInModuleTypes.Add(plugInModuleType); } } return modules; } private void CreateModules(ICollection moduleTypes, List plugInModuleTypes) { foreach (var moduleType in moduleTypes) { var moduleObject = _iocManager.Resolve(moduleType) as AbpModule; if (moduleObject == null) { throw new AbpInitializationException("This type is not an ABP module: " + moduleType.AssemblyQualifiedName); } moduleObject.IocManager = _iocManager; moduleObject.Configuration = _iocManager.Resolve(); var moduleInfo = new AbpModuleInfo(moduleType, moduleObject, plugInModuleTypes.Contains(moduleType)); _modules.Add(moduleInfo); if (moduleType == _modules.StartupModuleType) { StartupModule = moduleInfo; } Logger.DebugFormat("Loaded module: " + moduleType.AssemblyQualifiedName); } } private void RegisterModules(ICollection moduleTypes) { foreach (var moduleType in moduleTypes) { _iocManager.RegisterIfNot(moduleType); } } private void SetDependencies() { foreach (var moduleInfo in _modules) { moduleInfo.Dependencies.Clear(); //Set dependencies for defined DependsOnAttribute attribute(s). foreach (var dependedModuleType in AbpModule.FindDependedModuleTypes(moduleInfo.Type)) { var dependedModuleInfo = _modules.FirstOrDefault(m => m.Type == dependedModuleType); if (dependedModuleInfo == null) { throw new AbpInitializationException("Could not find a depended module " + dependedModuleType.AssemblyQualifiedName + " for " + moduleInfo.Type.AssemblyQualifiedName); } if ((moduleInfo.Dependencies.FirstOrDefault(dm => dm.Type == dependedModuleType) == null)) { moduleInfo.Dependencies.Add(dependedModuleInfo); } } } } } }