From 3729e2ead2d19eb8755271a6ee9605dbee2056b2 Mon Sep 17 00:00:00 2001
From: GwWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Fri, 2 Jan 2026 11:49:12 +0800
Subject: [PATCH] =?UTF-8?q?feat(architecture):=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=9E=B6=E6=9E=84=E5=88=9D=E5=A7=8B=E5=8C=96=E5=A4=B1=E8=B4=A5?=
=?UTF-8?q?=E5=A4=84=E7=90=86=E5=92=8C=E9=98=B6=E6=AE=B5=E8=BD=AC=E6=8D=A2?=
=?UTF-8?q?=E8=A7=84=E5=88=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将 CurrentPhase 属性改为公共读取私有设置
- 在 Initialize 和 InitializeAsync 方法中添加异常处理机制
- 添加 ArchitectureFailedInitializationEvent 事件类型
- 定义架构阶段转换规则,支持失败初始化状态转换
- 添加 FailedInitialization 枚举值
- 在同步测试架构中添加后注册钩子功能
- 重构测试基类,移除重复的测试方法
- 添加架构初始化失败时的错误日志记录
- 实现初始化失败时自动进入 FailedInitialization 阶段
---
.../enums/ArchitecturePhase.cs | 7 +-
.../architecture/SyncTestArchitecture.cs | 32 +++++-
.../tests/ArchitectureTestsBase.cs | 95 +----------------
.../tests/SyncArchitectureTests.cs | 100 +++++++++++++-----
GFramework.Core/architecture/Architecture.cs | 27 ++++-
.../architecture/ArchitectureConstants.cs | 30 +++++-
GFramework.Core/events/ArchitectureEvents.cs | 6 ++
7 files changed, 165 insertions(+), 132 deletions(-)
diff --git a/GFramework.Core.Abstractions/enums/ArchitecturePhase.cs b/GFramework.Core.Abstractions/enums/ArchitecturePhase.cs
index bb396f9..a46310c 100644
--- a/GFramework.Core.Abstractions/enums/ArchitecturePhase.cs
+++ b/GFramework.Core.Abstractions/enums/ArchitecturePhase.cs
@@ -47,5 +47,10 @@ public enum ArchitecturePhase
///
/// 已销毁 暂时不使用
///
- Destroyed
+ Destroyed,
+
+ ///
+ /// 初始化失败 暂时不使用
+ ///
+ FailedInitialization
}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/architecture/SyncTestArchitecture.cs b/GFramework.Core.Tests/architecture/SyncTestArchitecture.cs
index 20bba26..a19c94e 100644
--- a/GFramework.Core.Tests/architecture/SyncTestArchitecture.cs
+++ b/GFramework.Core.Tests/architecture/SyncTestArchitecture.cs
@@ -6,25 +6,55 @@ using GFramework.Core.Tests.system;
namespace GFramework.Core.Tests.architecture;
+///
+/// 同步测试架构类,用于测试架构的生命周期和事件处理
+///
public sealed class SyncTestArchitecture : Architecture
{
+ private Action? _postRegistrationHook;
+
+ ///
+ /// 获取就绪事件是否已触发的状态
+ ///
public bool ReadyEventFired { get; private set; }
+
+ ///
+ /// 获取初始化方法是否已调用的状态
+ ///
public bool InitCalled { get; private set; }
- public List PhaseHistory { get; } = new();
+ ///
+ /// 获取架构阶段历史记录列表
+ ///
+ public List PhaseHistory { get; } = [];
+ ///
+ /// 添加注册后钩子函数
+ ///
+ /// 要添加的钩子函数
+ public void AddPostRegistrationHook(Action hook) => _postRegistrationHook = hook;
+
+ ///
+ /// 初始化架构组件,注册模型、系统并设置事件监听器
+ ///
protected override void Init()
{
InitCalled = true;
RegisterModel(new TestModel());
RegisterSystem(new TestSystem());
+ _postRegistrationHook?.Invoke(this);
Context.RegisterEvent(_ => { ReadyEventFired = true; });
}
+ ///
+ /// 进入指定架构阶段时的处理方法,记录阶段历史
+ ///
+ /// 要进入的下一个架构阶段
protected override void EnterPhase(ArchitecturePhase next)
{
base.EnterPhase(next);
+ // 记录进入的架构阶段到历史列表中
PhaseHistory.Add(next);
}
}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/tests/ArchitectureTestsBase.cs b/GFramework.Core.Tests/tests/ArchitectureTestsBase.cs
index 3ccb9ee..c756db6 100644
--- a/GFramework.Core.Tests/tests/ArchitectureTestsBase.cs
+++ b/GFramework.Core.Tests/tests/ArchitectureTestsBase.cs
@@ -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 where TArchitecture :
/// 创建的架构实例
protected abstract TArchitecture CreateArchitecture();
- ///
- /// 子类必须实现初始化架构(同步或异步)
- ///
- /// 异步初始化任务
- protected abstract Task InitializeArchitecture();
-
///
/// 测试设置方法,在每个测试开始前执行
/// 清理游戏上下文并创建架构实例
@@ -57,85 +45,4 @@ public abstract class ArchitectureTestsBase where TArchitecture :
Architecture = null;
}
}
-
- ///
- /// 验证架构阶段顺序
- ///
- /// 异步测试任务
- [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)phasesProperty!.GetValue(Architecture)!;
-
- CollectionAssert.AreEqual(
- new[]
- {
- ArchitecturePhase.BeforeModelInit,
- ArchitecturePhase.AfterModelInit,
- ArchitecturePhase.BeforeSystemInit,
- ArchitecturePhase.AfterSystemInit,
- ArchitecturePhase.Ready
- },
- phases
- );
- }
-
- ///
- /// 验证 Ready 后不能注册组件
- ///
- /// 异步测试任务
- [Test]
- public async Task Registering_Components_AfterReady_Should_Throw()
- {
- await InitializeArchitecture();
-
- // 根据架构类型验证注册组件时抛出异常
- if (Architecture is SyncTestArchitecture syncArch)
- {
- Assert.Throws(() => syncArch.RegisterModel(new TestModel()));
- Assert.Throws(() => syncArch.RegisterSystem(new TestSystem()));
- }
- else if (Architecture is AsyncTestArchitecture asyncArch)
- {
- Assert.Throws(() => asyncArch.RegisterModel(new AsyncTestModel()));
- Assert.Throws(() => asyncArch.RegisterSystem(new AsyncTestSystem()));
- }
- }
-
- ///
- /// 验证销毁功能
- ///
- /// 异步测试任务
- [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();
- Assert.That(system!.DestroyCalled, Is.True);
- }
- else if (Architecture is AsyncTestArchitecture asyncArch)
- {
- var system = asyncArch.Context.GetSystem();
- 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));
- }
}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/tests/SyncArchitectureTests.cs b/GFramework.Core.Tests/tests/SyncArchitectureTests.cs
index bbe266f..99e3124 100644
--- a/GFramework.Core.Tests/tests/SyncArchitectureTests.cs
+++ b/GFramework.Core.Tests/tests/SyncArchitectureTests.cs
@@ -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;
///
-/// 同步架构测试类,用于测试同步架构的功能和行为
+/// 同步架构测试类,用于测试同步架构的初始化、生命周期和组件注册等功能
///
-///
-/// 该测试类使用非并行执行模式,确保测试的隔离性和可靠性
-///
[TestFixture]
[NonParallelizable]
public class SyncArchitectureTests : ArchitectureTestsBase
{
- ///
- /// 创建同步测试架构实例
- ///
- /// SyncTestArchitecture实例
- protected override SyncTestArchitecture CreateArchitecture() => new SyncTestArchitecture();
-
- ///
- /// 初始化架构异步方法
- ///
- /// 表示异步操作的Task
- protected override Task InitializeArchitecture()
- {
- Architecture!.Initialize();
- return Task.CompletedTask;
- }
+ protected override SyncTestArchitecture CreateArchitecture() => new();
///
/// 测试架构是否正确初始化所有组件
@@ -49,11 +32,7 @@ public class SyncArchitectureTests : ArchitectureTestsBase
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
Assert.That(ctx, Is.Not.Null);
}
+ ///
+ /// 测试架构是否按正确顺序进入各个阶段
+ /// 验证架构初始化过程中各阶段的执行顺序
+ ///
+ [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
+ );
+ }
+
+ ///
+ /// 测试在架构就绪后注册系统是否抛出异常(当不允许时)
+ ///
+ [Test]
+ public void RegisterSystem_AfterReady_Should_Throw_When_NotAllowed()
+ {
+ Architecture!.Initialize();
+
+ Assert.Throws(() => { Architecture.RegisterSystem(new TestSystem()); });
+ }
+
+ ///
+ /// 测试在架构就绪后注册模型是否抛出异常(当不允许时)
+ ///
+ [Test]
+ public void RegisterModel_AfterReady_Should_Throw_When_NotAllowed()
+ {
+ Architecture!.Initialize();
+
+ Assert.Throws(() => { Architecture.RegisterModel(new TestModel()); });
+ }
+
+ ///
+ /// 测试架构销毁功能,验证销毁后系统被正确销毁且架构进入销毁阶段
+ ///
+ [Test]
+ public void Architecture_Destroy_Should_Destroy_All_Systems_And_Enter_Destroyed()
+ {
+ Architecture!.Initialize();
+ Architecture.Destroy();
+
+ var system = Architecture.Context.GetSystem();
+ Assert.That(system!.DestroyCalled, Is.True);
+
+ var phase = Architecture.CurrentPhase;
+ Assert.That(phase, Is.EqualTo(ArchitecturePhase.Destroyed));
+ }
+
///
/// 测试当模型初始化失败时架构是否停止初始化
///
[Test]
public void Architecture_Should_Stop_Initialization_When_Model_Init_Fails()
{
- Architecture!.RegisterModel(new FailingModel());
-
- Assert.Throws(() => { Architecture!.Initialize(); });
+ Architecture!.AddPostRegistrationHook(architecture => { architecture.RegisterModel(new FailingModel()); });
+ // 调用初始化
+ Architecture.Initialize();
+ Assert.That(Architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.FailedInitialization));
}
}
\ No newline at end of file
diff --git a/GFramework.Core/architecture/Architecture.cs b/GFramework.Core/architecture/Architecture.cs
index 169966d..1638474 100644
--- a/GFramework.Core/architecture/Architecture.cs
+++ b/GFramework.Core/architecture/Architecture.cs
@@ -112,7 +112,7 @@ public abstract class Architecture(
///
/// 当前架构的阶段
///
- private ArchitecturePhase CurrentPhase { get; set; }
+ public ArchitecturePhase CurrentPhase { get; private set; }
///
/// 日志记录器实例,用于记录应用程序的运行日志
@@ -236,7 +236,17 @@ public abstract class Architecture(
///
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());
+ }
}
///
@@ -245,7 +255,18 @@ public abstract class Architecture(
/// 表示异步初始化操作的Task
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;
+ }
}
///
diff --git a/GFramework.Core/architecture/ArchitectureConstants.cs b/GFramework.Core/architecture/ArchitectureConstants.cs
index f7658cf..a0bd243 100644
--- a/GFramework.Core/architecture/ArchitectureConstants.cs
+++ b/GFramework.Core/architecture/ArchitectureConstants.cs
@@ -3,17 +3,39 @@ using GFramework.Core.Abstractions.enums;
namespace GFramework.Core.architecture;
+///
+/// 架构常量类,定义了架构阶段转换规则
+///
public static class ArchitectureConstants
{
+ ///
+ /// 定义架构阶段之间的有效转换关系
+ ///
+ ///
+ /// 键为当前架构阶段,值为从该阶段可以转换到的下一阶段数组
+ ///
public static readonly ImmutableDictionary PhaseTransitions =
new Dictionary
{
{ 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();
}
\ No newline at end of file
diff --git a/GFramework.Core/events/ArchitectureEvents.cs b/GFramework.Core/events/ArchitectureEvents.cs
index 8a77c03..9146cfe 100644
--- a/GFramework.Core/events/ArchitectureEvents.cs
+++ b/GFramework.Core/events/ArchitectureEvents.cs
@@ -22,4 +22,10 @@ public static class ArchitectureEvents
/// 当架构完全销毁完成后触发此事件,表示系统已关闭
///
public readonly struct ArchitectureDestroyedEvent;
+
+ ///
+ /// 架构初始化失败事件
+ /// 当架构初始化过程中发生错误时触发此事件
+ ///
+ public readonly struct ArchitectureFailedInitializationEvent;
}
\ No newline at end of file