feat(architecture): 添加架构初始化失败处理和阶段转换规则

- 将 CurrentPhase 属性改为公共读取私有设置
- 在 Initialize 和 InitializeAsync 方法中添加异常处理机制
- 添加 ArchitectureFailedInitializationEvent 事件类型
- 定义架构阶段转换规则,支持失败初始化状态转换
- 添加 FailedInitialization 枚举值
- 在同步测试架构中添加后注册钩子功能
- 重构测试基类,移除重复的测试方法
- 添加架构初始化失败时的错误日志记录
- 实现初始化失败时自动进入 FailedInitialization 阶段
This commit is contained in:
GwWuYou 2026-01-02 11:49:12 +08:00
parent 78da01878b
commit 3729e2ead2
7 changed files with 165 additions and 132 deletions

View File

@ -47,5 +47,10 @@ public enum ArchitecturePhase
/// <summary>
/// 已销毁 暂时不使用
/// </summary>
Destroyed
Destroyed,
/// <summary>
/// 初始化失败 暂时不使用
/// </summary>
FailedInitialization
}

View File

@ -6,25 +6,55 @@ using GFramework.Core.Tests.system;
namespace GFramework.Core.Tests.architecture;
/// <summary>
/// 同步测试架构类,用于测试架构的生命周期和事件处理
/// </summary>
public sealed class SyncTestArchitecture : Architecture
{
private Action<SyncTestArchitecture>? _postRegistrationHook;
/// <summary>
/// 获取就绪事件是否已触发的状态
/// </summary>
public bool ReadyEventFired { get; private set; }
/// <summary>
/// 获取初始化方法是否已调用的状态
/// </summary>
public bool InitCalled { get; private set; }
public List<ArchitecturePhase> PhaseHistory { get; } = new();
/// <summary>
/// 获取架构阶段历史记录列表
/// </summary>
public List<ArchitecturePhase> PhaseHistory { get; } = [];
/// <summary>
/// 添加注册后钩子函数
/// </summary>
/// <param name="hook">要添加的钩子函数</param>
public void AddPostRegistrationHook(Action<SyncTestArchitecture> hook) => _postRegistrationHook = hook;
/// <summary>
/// 初始化架构组件,注册模型、系统并设置事件监听器
/// </summary>
protected override void Init()
{
InitCalled = true;
RegisterModel(new TestModel());
RegisterSystem(new TestSystem());
_postRegistrationHook?.Invoke(this);
Context.RegisterEvent<ArchitectureEvents.ArchitectureLifecycleReadyEvent>(_ => { ReadyEventFired = true; });
}
/// <summary>
/// 进入指定架构阶段时的处理方法,记录阶段历史
/// </summary>
/// <param name="next">要进入的下一个架构阶段</param>
protected override void EnterPhase(ArchitecturePhase next)
{
base.EnterPhase(next);
// 记录进入的架构阶段到历史列表中
PhaseHistory.Add(next);
}
}

View File

@ -1,11 +1,5 @@
using System.Reflection;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.architecture;
using GFramework.Core.Tests.architecture;
using GFramework.Core.Tests.model;
using GFramework.Core.Tests.system;
using GFramework.Core.architecture;
using NUnit.Framework;
using NUnit.Framework.Legacy;
namespace GFramework.Core.Tests.tests;
@ -23,12 +17,6 @@ public abstract class ArchitectureTestsBase<TArchitecture> where TArchitecture :
/// <returns>创建的架构实例</returns>
protected abstract TArchitecture CreateArchitecture();
/// <summary>
/// 子类必须实现初始化架构(同步或异步)
/// </summary>
/// <returns>异步初始化任务</returns>
protected abstract Task InitializeArchitecture();
/// <summary>
/// 测试设置方法,在每个测试开始前执行
/// 清理游戏上下文并创建架构实例
@ -57,85 +45,4 @@ public abstract class ArchitectureTestsBase<TArchitecture> where TArchitecture :
Architecture = null;
}
}
/// <summary>
/// 验证架构阶段顺序
/// </summary>
/// <returns>异步测试任务</returns>
[Test]
public async Task Architecture_Should_Enter_Phases_In_Correct_Order()
{
await InitializeArchitecture();
// 通过反射获取架构的阶段历史记录
var phasesProperty = typeof(TArchitecture)
.GetProperty("PhaseHistory", BindingFlags.Instance | BindingFlags.Public);
var phases = (List<ArchitecturePhase>)phasesProperty!.GetValue(Architecture)!;
CollectionAssert.AreEqual(
new[]
{
ArchitecturePhase.BeforeModelInit,
ArchitecturePhase.AfterModelInit,
ArchitecturePhase.BeforeSystemInit,
ArchitecturePhase.AfterSystemInit,
ArchitecturePhase.Ready
},
phases
);
}
/// <summary>
/// 验证 Ready 后不能注册组件
/// </summary>
/// <returns>异步测试任务</returns>
[Test]
public async Task Registering_Components_AfterReady_Should_Throw()
{
await InitializeArchitecture();
// 根据架构类型验证注册组件时抛出异常
if (Architecture is SyncTestArchitecture syncArch)
{
Assert.Throws<InvalidOperationException>(() => syncArch.RegisterModel(new TestModel()));
Assert.Throws<InvalidOperationException>(() => syncArch.RegisterSystem(new TestSystem()));
}
else if (Architecture is AsyncTestArchitecture asyncArch)
{
Assert.Throws<InvalidOperationException>(() => asyncArch.RegisterModel(new AsyncTestModel()));
Assert.Throws<InvalidOperationException>(() => asyncArch.RegisterSystem(new AsyncTestSystem()));
}
}
/// <summary>
/// 验证销毁功能
/// </summary>
/// <returns>异步测试任务</returns>
[Test]
public async Task Architecture_Destroy_Should_Destroy_All_Systems_And_Enter_Destroyed()
{
await InitializeArchitecture();
Architecture!.Destroy();
// 验证系统是否被正确销毁
if (Architecture is SyncTestArchitecture syncArch)
{
var system = syncArch.Context.GetSystem<TestSystem>();
Assert.That(system!.DestroyCalled, Is.True);
}
else if (Architecture is AsyncTestArchitecture asyncArch)
{
var system = asyncArch.Context.GetSystem<AsyncTestSystem>();
Assert.That(system!.DestroyCalled, Is.True);
}
// 通过反射验证当前阶段为销毁状态
var phaseProperty = typeof(TArchitecture)
.GetProperty("CurrentPhase", BindingFlags.Instance | BindingFlags.NonPublic);
var phase = (ArchitecturePhase)phaseProperty!.GetValue(Architecture)!;
Assert.That(phase, Is.EqualTo(ArchitecturePhase.Destroyed));
}
}

View File

@ -1,38 +1,21 @@
using System.Reflection;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.architecture;
using GFramework.Core.Tests.architecture;
using GFramework.Core.Tests.model;
using GFramework.Core.Tests.system;
using NUnit.Framework;
using NUnit.Framework.Legacy;
namespace GFramework.Core.Tests.tests;
/// <summary>
/// 同步架构测试类,用于测试同步架构的功能和行为
/// 同步架构测试类,用于测试同步架构的初始化、生命周期和组件注册等功能
/// </summary>
/// <remarks>
/// 该测试类使用非并行执行模式,确保测试的隔离性和可靠性
/// </remarks>
[TestFixture]
[NonParallelizable]
public class SyncArchitectureTests : ArchitectureTestsBase<SyncTestArchitecture>
{
/// <summary>
/// 创建同步测试架构实例
/// </summary>
/// <returns>SyncTestArchitecture实例</returns>
protected override SyncTestArchitecture CreateArchitecture() => new SyncTestArchitecture();
/// <summary>
/// 初始化架构异步方法
/// </summary>
/// <returns>表示异步操作的Task</returns>
protected override Task InitializeArchitecture()
{
Architecture!.Initialize();
return Task.CompletedTask;
}
protected override SyncTestArchitecture CreateArchitecture() => new();
/// <summary>
/// 测试架构是否正确初始化所有组件
@ -49,11 +32,7 @@ public class SyncArchitectureTests : ArchitectureTestsBase<SyncTestArchitecture>
Assert.That(Architecture.Runtime, Is.Not.Null);
// 通过反射获取当前架构阶段
var phaseProperty = typeof(Architecture)
.GetProperty("CurrentPhase", BindingFlags.Instance | BindingFlags.NonPublic);
var phase = (ArchitecturePhase)phaseProperty!.GetValue(Architecture)!;
var phase = Architecture.CurrentPhase;
Assert.That(phase, Is.EqualTo(ArchitecturePhase.Ready));
var context = Architecture.Context;
@ -80,14 +59,77 @@ public class SyncArchitectureTests : ArchitectureTestsBase<SyncTestArchitecture>
Assert.That(ctx, Is.Not.Null);
}
/// <summary>
/// 测试架构是否按正确顺序进入各个阶段
/// 验证架构初始化过程中各阶段的执行顺序
/// </summary>
[Test]
public void Architecture_Should_Enter_Phases_In_Correct_Order()
{
Architecture!.Initialize();
var phases = Architecture.PhaseHistory;
CollectionAssert.AreEqual(
new[]
{
ArchitecturePhase.BeforeModelInit,
ArchitecturePhase.AfterModelInit,
ArchitecturePhase.BeforeSystemInit,
ArchitecturePhase.AfterSystemInit,
ArchitecturePhase.Ready
},
phases
);
}
/// <summary>
/// 测试在架构就绪后注册系统是否抛出异常(当不允许时)
/// </summary>
[Test]
public void RegisterSystem_AfterReady_Should_Throw_When_NotAllowed()
{
Architecture!.Initialize();
Assert.Throws<InvalidOperationException>(() => { Architecture.RegisterSystem(new TestSystem()); });
}
/// <summary>
/// 测试在架构就绪后注册模型是否抛出异常(当不允许时)
/// </summary>
[Test]
public void RegisterModel_AfterReady_Should_Throw_When_NotAllowed()
{
Architecture!.Initialize();
Assert.Throws<InvalidOperationException>(() => { Architecture.RegisterModel(new TestModel()); });
}
/// <summary>
/// 测试架构销毁功能,验证销毁后系统被正确销毁且架构进入销毁阶段
/// </summary>
[Test]
public void Architecture_Destroy_Should_Destroy_All_Systems_And_Enter_Destroyed()
{
Architecture!.Initialize();
Architecture.Destroy();
var system = Architecture.Context.GetSystem<TestSystem>();
Assert.That(system!.DestroyCalled, Is.True);
var phase = Architecture.CurrentPhase;
Assert.That(phase, Is.EqualTo(ArchitecturePhase.Destroyed));
}
/// <summary>
/// 测试当模型初始化失败时架构是否停止初始化
/// </summary>
[Test]
public void Architecture_Should_Stop_Initialization_When_Model_Init_Fails()
{
Architecture!.RegisterModel(new FailingModel());
Assert.Throws<InvalidOperationException>(() => { Architecture!.Initialize(); });
Architecture!.AddPostRegistrationHook(architecture => { architecture.RegisterModel(new FailingModel()); });
// 调用初始化
Architecture.Initialize();
Assert.That(Architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.FailedInitialization));
}
}

View File

@ -112,7 +112,7 @@ public abstract class Architecture(
/// <summary>
/// 当前架构的阶段
/// </summary>
private ArchitecturePhase CurrentPhase { get; set; }
public ArchitecturePhase CurrentPhase { get; private set; }
/// <summary>
/// 日志记录器实例,用于记录应用程序的运行日志
@ -236,7 +236,17 @@ public abstract class Architecture(
/// </summary>
public void Initialize()
{
InitializeInternalAsync(asyncMode: false).GetAwaiter().GetResult();
try
{
InitializeInternalAsync(asyncMode: false).GetAwaiter().GetResult();
}
catch (Exception e)
{
_logger.Error("Architecture initialization failed:", e);
EnterPhase(ArchitecturePhase.FailedInitialization);
// 发送初始化失败事件
TypeEventSystem.Send(new ArchitectureEvents.ArchitectureFailedInitializationEvent());
}
}
/// <summary>
@ -245,7 +255,18 @@ public abstract class Architecture(
/// <returns>表示异步初始化操作的Task</returns>
public Task InitializeAsync()
{
return InitializeInternalAsync(asyncMode: true);
try
{
return InitializeInternalAsync(asyncMode: true);
}
catch (Exception e)
{
_logger.Error("Architecture initialization failed:", e);
EnterPhase(ArchitecturePhase.FailedInitialization);
// 发送初始化失败事件
TypeEventSystem.Send(new ArchitectureEvents.ArchitectureFailedInitializationEvent());
return Task.CompletedTask;
}
}
/// <summary>

View File

@ -3,17 +3,39 @@ using GFramework.Core.Abstractions.enums;
namespace GFramework.Core.architecture;
/// <summary>
/// 架构常量类,定义了架构阶段转换规则
/// </summary>
public static class ArchitectureConstants
{
/// <summary>
/// 定义架构阶段之间的有效转换关系
/// </summary>
/// <remarks>
/// 键为当前架构阶段,值为从该阶段可以转换到的下一阶段数组
/// </remarks>
public static readonly ImmutableDictionary<ArchitecturePhase, ArchitecturePhase[]> PhaseTransitions =
new Dictionary<ArchitecturePhase, ArchitecturePhase[]>
{
{ ArchitecturePhase.None, [ArchitecturePhase.BeforeModelInit] },
{ ArchitecturePhase.BeforeModelInit, [ArchitecturePhase.AfterModelInit] },
{ ArchitecturePhase.AfterModelInit, [ArchitecturePhase.BeforeSystemInit] },
{ ArchitecturePhase.BeforeSystemInit, [ArchitecturePhase.AfterSystemInit] },
{ ArchitecturePhase.AfterSystemInit, [ArchitecturePhase.Ready] },
{
ArchitecturePhase.BeforeModelInit, [
ArchitecturePhase.AfterModelInit, ArchitecturePhase.FailedInitialization
]
},
{
ArchitecturePhase.AfterModelInit, [
ArchitecturePhase.BeforeSystemInit, ArchitecturePhase.FailedInitialization
]
},
{
ArchitecturePhase.BeforeSystemInit, [
ArchitecturePhase.AfterSystemInit, ArchitecturePhase.FailedInitialization
]
},
{ ArchitecturePhase.AfterSystemInit, [ArchitecturePhase.Ready, ArchitecturePhase.FailedInitialization] },
{ ArchitecturePhase.Ready, [ArchitecturePhase.Destroying] },
{ ArchitecturePhase.FailedInitialization, [ArchitecturePhase.Destroying] },
{ ArchitecturePhase.Destroying, [ArchitecturePhase.Destroyed] }
}.ToImmutableDictionary();
}

View File

@ -22,4 +22,10 @@ public static class ArchitectureEvents
/// 当架构完全销毁完成后触发此事件,表示系统已关闭
/// </summary>
public readonly struct ArchitectureDestroyedEvent;
/// <summary>
/// 架构初始化失败事件
/// 当架构初始化过程中发生错误时触发此事件
/// </summary>
public readonly struct ArchitectureFailedInitializationEvent;
}