mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
feat(architecture): 添加架构初始化失败处理和阶段转换规则
- 将 CurrentPhase 属性改为公共读取私有设置 - 在 Initialize 和 InitializeAsync 方法中添加异常处理机制 - 添加 ArchitectureFailedInitializationEvent 事件类型 - 定义架构阶段转换规则,支持失败初始化状态转换 - 添加 FailedInitialization 枚举值 - 在同步测试架构中添加后注册钩子功能 - 重构测试基类,移除重复的测试方法 - 添加架构初始化失败时的错误日志记录 - 实现初始化失败时自动进入 FailedInitialization 阶段
This commit is contained in:
parent
78da01878b
commit
3729e2ead2
@ -47,5 +47,10 @@ public enum ArchitecturePhase
|
||||
/// <summary>
|
||||
/// 已销毁 暂时不使用
|
||||
/// </summary>
|
||||
Destroyed
|
||||
Destroyed,
|
||||
|
||||
/// <summary>
|
||||
/// 初始化失败 暂时不使用
|
||||
/// </summary>
|
||||
FailedInitialization
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -22,4 +22,10 @@ public static class ArchitectureEvents
|
||||
/// 当架构完全销毁完成后触发此事件,表示系统已关闭
|
||||
/// </summary>
|
||||
public readonly struct ArchitectureDestroyedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// 架构初始化失败事件
|
||||
/// 当架构初始化过程中发生错误时触发此事件
|
||||
/// </summary>
|
||||
public readonly struct ArchitectureFailedInitializationEvent;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user