mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
feat(architecture): 添加异步销毁功能支持
- 在 Architecture 中添加对 IAsyncDestroyable 接口的支持 - 将销毁集合类型从 IDestroyable 改为 object 以支持多种销毁接口 - 实现 DestroyAsync 方法提供异步销毁能力 - 保留旧的同步 Destroy 方法用于向后兼容 - 在 StateMachineSystem 中添加异步销毁状态的支持 - 添加 IAsyncDestroyable、IAsyncInitializable 和 IAsyncLifecycle 接口定义 - 更新测试代码以使用新的异步销毁方法 - 在架构销毁时清理依赖注入容器
This commit is contained in:
parent
73d1fcf6fd
commit
56769cbf01
@ -1,3 +1,4 @@
|
|||||||
|
using GFramework.Core.Abstractions.lifecycle;
|
||||||
using GFramework.Core.Abstractions.model;
|
using GFramework.Core.Abstractions.model;
|
||||||
using GFramework.Core.Abstractions.system;
|
using GFramework.Core.Abstractions.system;
|
||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.utility;
|
||||||
|
|||||||
13
GFramework.Core.Abstractions/lifecycle/IAsyncDestroyable.cs
Normal file
13
GFramework.Core.Abstractions/lifecycle/IAsyncDestroyable.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.lifecycle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定义异步销毁接口,用于需要异步清理资源的组件
|
||||||
|
/// </summary>
|
||||||
|
public interface IAsyncDestroyable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 异步销毁方法,在组件关闭时调用
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>表示异步销毁操作的任务</returns>
|
||||||
|
ValueTask DestroyAsync();
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义异步初始化接口,用于需要异步初始化的组件或服务
|
/// 定义异步初始化接口,用于需要异步初始化的组件或服务
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.lifecycle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定义异步生命周期接口,组合了异步初始化和异步销毁
|
||||||
|
/// </summary>
|
||||||
|
public interface IAsyncLifecycle : IAsyncInitializable, IAsyncDestroyable
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
using GFramework.Core.Abstractions.architecture;
|
|
||||||
using GFramework.Core.Abstractions.enums;
|
using GFramework.Core.Abstractions.enums;
|
||||||
|
using GFramework.Core.Abstractions.lifecycle;
|
||||||
using GFramework.Core.model;
|
using GFramework.Core.model;
|
||||||
|
|
||||||
namespace GFramework.Core.Tests.model;
|
namespace GFramework.Core.Tests.model;
|
||||||
|
|||||||
@ -133,12 +133,12 @@ public class StateMachineSystemTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 测试Destroy方法不抛出异常
|
/// 测试DestroyAsync方法不抛出异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void Destroy_Should_Not_Throw_Exception()
|
public async Task DestroyAsync_Should_Not_Throw_Exception()
|
||||||
{
|
{
|
||||||
Assert.That(() => _stateMachine!.Destroy(), Throws.Nothing);
|
Assert.That(async () => await _stateMachine!.DestroyAsync(), Throws.Nothing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.architecture;
|
using GFramework.Core.Abstractions.architecture;
|
||||||
using GFramework.Core.Abstractions.enums;
|
using GFramework.Core.Abstractions.enums;
|
||||||
|
using GFramework.Core.Abstractions.lifecycle;
|
||||||
using GFramework.Core.Abstractions.system;
|
using GFramework.Core.Abstractions.system;
|
||||||
|
|
||||||
namespace GFramework.Core.Tests.system;
|
namespace GFramework.Core.Tests.system;
|
||||||
|
|||||||
@ -34,11 +34,14 @@ public abstract class ArchitectureTestsBase<TArchitecture> where TArchitecture :
|
|||||||
/// 销毁架构实例并清理游戏上下文
|
/// 销毁架构实例并清理游戏上下文
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public void TearDown()
|
public async Task TearDown()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Architecture?.Destroy();
|
if (Architecture != null)
|
||||||
|
{
|
||||||
|
await Architecture.DestroyAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@ -110,7 +110,7 @@ public class AsyncArchitectureTests : ArchitectureTestsBase<AsyncTestArchitectur
|
|||||||
public async Task Architecture_Destroy_Should_Destroy_All_Systems()
|
public async Task Architecture_Destroy_Should_Destroy_All_Systems()
|
||||||
{
|
{
|
||||||
await Architecture!.InitializeAsync();
|
await Architecture!.InitializeAsync();
|
||||||
Architecture.Destroy();
|
await Architecture.DestroyAsync();
|
||||||
|
|
||||||
var system = Architecture.Context.GetSystem<TestSystem>();
|
var system = Architecture.Context.GetSystem<TestSystem>();
|
||||||
Assert.That(system, Is.Null);
|
Assert.That(system, Is.Null);
|
||||||
|
|||||||
@ -114,10 +114,10 @@ public class SyncArchitectureTests : ArchitectureTestsBase<SyncTestArchitecture>
|
|||||||
/// 测试架构销毁功能,验证销毁后系统被正确销毁且架构进入销毁阶段
|
/// 测试架构销毁功能,验证销毁后系统被正确销毁且架构进入销毁阶段
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void Architecture_Destroy_Should_Destroy_All_Systems_And_Enter_Destroyed()
|
public async Task Architecture_Destroy_Should_Destroy_All_Systems_And_Enter_Destroyed()
|
||||||
{
|
{
|
||||||
Architecture!.Initialize();
|
Architecture!.Initialize();
|
||||||
Architecture.Destroy();
|
await Architecture.DestroyAsync();
|
||||||
|
|
||||||
var system = Architecture.Context.GetSystem<TestSystem>();
|
var system = Architecture.Context.GetSystem<TestSystem>();
|
||||||
Assert.That(system!.DestroyCalled, Is.True);
|
Assert.That(system!.DestroyCalled, Is.True);
|
||||||
|
|||||||
@ -114,14 +114,14 @@ public abstract class Architecture(
|
|||||||
private readonly List<IInitializable> _pendingInitializableList = [];
|
private readonly List<IInitializable> _pendingInitializableList = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可销毁组件的去重集合
|
/// 可销毁组件的去重集合(支持 IDestroyable 和 IAsyncDestroyable)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly HashSet<IDestroyable> _disposableSet = [];
|
private readonly HashSet<object> _disposableSet = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储所有需要销毁的组件(统一管理,保持注册逆序销毁)
|
/// 存储所有需要销毁的组件(统一管理,保持注册逆序销毁)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly List<IDestroyable> _disposables = [];
|
private readonly List<object> _disposables = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生命周期感知对象列表
|
/// 生命周期感知对象列表
|
||||||
@ -260,13 +260,15 @@ public abstract class Architecture(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理销毁
|
// 处理销毁(支持 IDestroyable 或 IAsyncDestroyable)
|
||||||
if (component is not IDestroyable disposable) return;
|
if (component is IDestroyable or IAsyncDestroyable)
|
||||||
// 原子去重:HashSet.Add 返回 true 表示添加成功(之前不存在)
|
|
||||||
if (_disposableSet.Add(disposable))
|
|
||||||
{
|
{
|
||||||
_disposables.Add(disposable);
|
// 原子去重:HashSet.Add 返回 true 表示添加成功(之前不存在)
|
||||||
_logger.Trace($"Registered {component.GetType().Name} for destruction");
|
if (_disposableSet.Add(component))
|
||||||
|
{
|
||||||
|
_disposables.Add(component);
|
||||||
|
_logger.Trace($"Registered {component.GetType().Name} for destruction");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,9 +363,9 @@ public abstract class Architecture(
|
|||||||
protected abstract void Init();
|
protected abstract void Init();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 销毁架构并清理所有组件资源
|
/// 异步销毁架构及所有组件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Destroy()
|
public virtual async ValueTask DestroyAsync()
|
||||||
{
|
{
|
||||||
// 检查当前阶段,如果已经处于销毁或已销毁状态则直接返回
|
// 检查当前阶段,如果已经处于销毁或已销毁状态则直接返回
|
||||||
if (CurrentPhase >= ArchitecturePhase.Destroying)
|
if (CurrentPhase >= ArchitecturePhase.Destroying)
|
||||||
@ -376,32 +378,51 @@ public abstract class Architecture(
|
|||||||
_logger.Info("Starting architecture destruction");
|
_logger.Info("Starting architecture destruction");
|
||||||
EnterPhase(ArchitecturePhase.Destroying);
|
EnterPhase(ArchitecturePhase.Destroying);
|
||||||
|
|
||||||
// 销毁所有实现了 IDestroyable 的组件(按注册逆序销毁)
|
// 销毁所有实现了 IAsyncDestroyable 或 IDestroyable 的组件(按注册逆序销毁)
|
||||||
_logger.Info($"Destroying {_disposables.Count} disposable components");
|
_logger.Info($"Destroying {_disposables.Count} disposable components");
|
||||||
|
|
||||||
for (var i = _disposables.Count - 1; i >= 0; i--)
|
for (var i = _disposables.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var disposable = _disposables[i];
|
var component = _disposables[i];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.Debug($"Destroying component: {disposable.GetType().Name}");
|
_logger.Debug($"Destroying component: {component.GetType().Name}");
|
||||||
disposable.Destroy();
|
|
||||||
|
// 优先使用异步销毁
|
||||||
|
if (component is IAsyncDestroyable asyncDestroyable)
|
||||||
|
{
|
||||||
|
await asyncDestroyable.DestroyAsync();
|
||||||
|
}
|
||||||
|
else if (component is IDestroyable destroyable)
|
||||||
|
{
|
||||||
|
destroyable.Destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error($"Error destroying {disposable.GetType().Name}", ex);
|
_logger.Error($"Error destroying {component.GetType().Name}", ex);
|
||||||
// 继续销毁其他组件,不会因为一个组件失败而中断
|
// 继续销毁其他组件,不会因为一个组件失败而中断
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_disposables.Clear();
|
_disposables.Clear();
|
||||||
_disposableSet.Clear();
|
_disposableSet.Clear();
|
||||||
|
Container.Clear();
|
||||||
|
|
||||||
// 进入已销毁阶段
|
// 进入已销毁阶段
|
||||||
EnterPhase(ArchitecturePhase.Destroyed);
|
EnterPhase(ArchitecturePhase.Destroyed);
|
||||||
_logger.Info("Architecture destruction completed");
|
_logger.Info("Architecture destruction completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 销毁架构并清理所有组件资源(同步方法,保留用于向后兼容)
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("建议使用 DestroyAsync() 以支持异步清理")]
|
||||||
|
public virtual void Destroy()
|
||||||
|
{
|
||||||
|
DestroyAsync().AsTask().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Component Registration
|
#region Component Registration
|
||||||
|
|||||||
@ -21,15 +21,26 @@ namespace GFramework.Core.state;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上下文感知异步状态基类
|
/// 上下文感知异步状态基类
|
||||||
/// 提供基础的异步状态管理功能和架构上下文访问能力
|
/// 提供基础的异步状态管理功能和架构上下文访问能力
|
||||||
/// 实现了IAsyncState(继承IState)和IContextAware接口
|
/// 实现了IAsyncState(继承IState)、IContextAware和IAsyncDestroyable接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AsyncContextAwareStateBase : IAsyncState, IContextAware, IDestroyable
|
public class AsyncContextAwareStateBase : IAsyncState, IContextAware, IDestroyable, IAsyncDestroyable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构上下文引用,用于访问架构相关的服务和数据
|
/// 架构上下文引用,用于访问架构相关的服务和数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IArchitectureContext? _context;
|
private IArchitectureContext? _context;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步销毁当前状态,释放相关资源
|
||||||
|
/// 子类可重写此方法以执行特定的异步清理操作
|
||||||
|
/// </summary>
|
||||||
|
public virtual ValueTask DestroyAsync()
|
||||||
|
{
|
||||||
|
// 默认实现:调用同步 Destroy()
|
||||||
|
Destroy();
|
||||||
|
return ValueTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
// ============ IState 同步方法显式实现(隐藏 + 运行时保护) ============
|
// ============ IState 同步方法显式实现(隐藏 + 运行时保护) ============
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -125,7 +136,7 @@ public class AsyncContextAwareStateBase : IAsyncState, IContextAware, IDestroyab
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 销毁当前状态,释放相关资源
|
/// 销毁当前状态,释放相关资源(同步方法,保留用于向后兼容)
|
||||||
/// 子类可重写此方法以执行特定的清理操作
|
/// 子类可重写此方法以执行特定的清理操作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Destroy()
|
public virtual void Destroy()
|
||||||
|
|||||||
@ -54,16 +54,25 @@ public class StateMachineSystem : StateMachine, IStateMachineSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 销毁方法,在系统关闭时调用
|
/// 销毁方法,在系统关闭时调用(同步方法,保留用于向后兼容)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("建议使用 DestroyAsync() 以支持异步清理")]
|
||||||
public virtual void Destroy()
|
public virtual void Destroy()
|
||||||
|
{
|
||||||
|
DestroyAsync().AsTask().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步销毁方法,在系统关闭时调用
|
||||||
|
/// </summary>
|
||||||
|
public virtual async ValueTask DestroyAsync()
|
||||||
{
|
{
|
||||||
// 退出当前状态
|
// 退出当前状态
|
||||||
if (Current != null)
|
if (Current != null)
|
||||||
{
|
{
|
||||||
if (Current is IAsyncState asyncState)
|
if (Current is IAsyncState asyncState)
|
||||||
{
|
{
|
||||||
asyncState.OnExitAsync(null);
|
await asyncState.OnExitAsync(null); // ✅ 正确等待异步清理
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -74,7 +83,17 @@ public class StateMachineSystem : StateMachine, IStateMachineSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清理所有状态
|
// 清理所有状态
|
||||||
foreach (var state in States.Values.OfType<IDestroyable>()) state.Destroy();
|
foreach (var state in States.Values)
|
||||||
|
{
|
||||||
|
if (state is IAsyncDestroyable asyncDestroyable)
|
||||||
|
{
|
||||||
|
await asyncDestroyable.DestroyAsync();
|
||||||
|
}
|
||||||
|
else if (state is IDestroyable destroyable)
|
||||||
|
{
|
||||||
|
destroyable.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
States.Clear();
|
States.Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user