using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Enums; using GFramework.Core.Abstractions.Lifecycle; using GFramework.Core.Abstractions.Logging; namespace GFramework.Core.Architectures; /// /// 统一处理架构内可销毁对象的登记与释放。 /// 该类型封装逆序销毁、异常隔离和服务模块清理规则, /// 让 可以专注于初始化流程本身。 /// internal sealed class ArchitectureDisposer( IArchitectureServices services, ILogger logger) { /// /// 保留注册顺序的可销毁对象列表。 /// 销毁时按逆序遍历,以尽量匹配组件间的依赖方向。 /// private readonly List _disposables = []; /// /// 用于去重的可销毁对象集合。 /// private readonly HashSet _disposableSet = []; /// /// 注册一个需要参与架构销毁流程的对象。 /// 只有实现 的对象会被跟踪。 /// /// 待检查的组件实例。 public void Register(object component) { if (component is not (IDestroyable or IAsyncDestroyable)) return; if (!_disposableSet.Add(component)) return; _disposables.Add(component); logger.Trace($"Registered {component.GetType().Name} for destruction"); } /// /// 执行架构销毁流程。 /// 该方法会根据当前阶段决定是否进入 Destroying/Destroyed 阶段,并负责服务模块与容器清理。 /// /// 销毁开始前的架构阶段。 /// 用于推进架构阶段的回调。 public async ValueTask DestroyAsync(ArchitecturePhase currentPhase, Action enterPhase) { if (currentPhase is ArchitecturePhase.Destroying or ArchitecturePhase.Destroyed) { logger.Warn("Architecture destroy called but already in destroying/destroyed state"); return; } if (currentPhase == ArchitecturePhase.None) { logger.Debug("Architecture destroy called but never initialized, cleaning up registered components"); await CleanupComponentsAsync(); return; } logger.Info("Starting architecture destruction"); enterPhase(ArchitecturePhase.Destroying); await CleanupComponentsAsync(); await services.ModuleManager.DestroyAllAsync(); // Destroyed 广播依赖容器中的阶段监听器,必须在清空容器前完成。 enterPhase(ArchitecturePhase.Destroyed); services.Container.Clear(); logger.Info("Architecture destruction completed"); } /// /// 逆序销毁当前已注册的所有可销毁组件。 /// 单个组件失败不会中断后续清理,避免在销毁阶段留下半清理状态。 /// private async ValueTask CleanupComponentsAsync() { logger.Info($"Destroying {_disposables.Count} disposable components"); for (var i = _disposables.Count - 1; i >= 0; i--) { var component = _disposables[i]; try { logger.Debug($"Destroying component: {component.GetType().Name}"); if (component is IAsyncDestroyable asyncDestroyable) { await asyncDestroyable.DestroyAsync(); } else if (component is IDestroyable destroyable) { destroyable.Destroy(); } } catch (Exception ex) { logger.Error($"Error destroying {component.GetType().Name}", ex); } } _disposables.Clear(); _disposableSet.Clear(); } }