using System.Reflection;
using NewLife.Studio.Core;
using NewLife.Log;
namespace NewLife.Studio.App.Services;
/// <summary>模块加载器 — 扫描已加载 Assembly 中实现 IStudioModule 的类型</summary>
public class ModuleLoader
{
private readonly List<ModuleInfo> _modules = [];
private ModuleInfo? _activeModule;
public IReadOnlyList<ModuleInfo> Modules => _modules.AsReadOnly();
public ModuleInfo? ActiveModule => _activeModule;
public event EventHandler<ModuleInfo>? ModuleActivated;
/// <summary>扫描所有已加载的 Assembly 中实现 IStudioModule 的类型</summary>
public void ScanModules()
{
_modules.Clear();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
if (type.IsAbstract || type.IsInterface)
continue;
if (!typeof(IStudioModule).IsAssignableFrom(type))
continue;
try
{
if (Activator.CreateInstance(type) is IStudioModule module)
{
_modules.Add(new ModuleInfo
{
Id = module.Id,
DisplayName = module.DisplayName,
Icon = module.Icon,
Order = module.Order,
Module = module
});
XTrace.WriteLine($"ModuleLoader: Found module [{module.Id}] {module.DisplayName} in {type.FullName}");
}
}
catch (Exception ex)
{
XTrace.WriteLine($"ModuleLoader: Failed to load module {type.FullName}: {ex.Message}");
}
}
}
_modules.Sort((a, b) => a.Order.CompareTo(b.Order));
XTrace.WriteLine($"ModuleLoader: Loaded {_modules.Count} modules");
}
/// <summary>激活默认模块(第一个)</summary>
public async Task ActivateDefaultAsync(CancellationToken ct = default)
{
if (_modules.Count > 0)
{
await ActivateModuleAsync(_modules[0], ct);
}
}
/// <summary>切换到指定模块</summary>
public async Task ActivateModuleAsync(ModuleInfo moduleInfo, CancellationToken ct = default)
{
if (_activeModule == moduleInfo)
return;
if (_activeModule != null)
{
await _activeModule.Module.OnDeactivateAsync(ct);
}
_activeModule = moduleInfo;
await moduleInfo.Module.OnActivateAsync(ct);
ModuleActivated?.Invoke(this, moduleInfo);
XTrace.WriteLine($"ModuleLoader: Activated module [{moduleInfo.Id}]");
}
}
|