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