mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
refactor(architecture): 重构架构阶段验证和初始化流程
- 修改阶段转换验证逻辑,允许从任何阶段转换到 FailedInitialization - 调整初始化流程,确保始终进入各个阶段而不仅仅是有组件时才进入 - 重新排列阶段转换顺序,实现线性状态机模式 - 添加架构阶段线性顺序定义数组 - 更新测试用例以验证初始化失败时抛出异常的情况
This commit is contained in:
parent
177de6d3e6
commit
f70254716b
@ -1,4 +1,4 @@
|
||||
using GFramework.Core.Abstractions.enums;
|
||||
using GFramework.Core.Abstractions.enums;
|
||||
using GFramework.Core.Tests.architecture;
|
||||
using GFramework.Core.Tests.model;
|
||||
using GFramework.Core.Tests.system;
|
||||
@ -94,7 +94,7 @@ public class AsyncArchitectureTests : ArchitectureTestsBase<AsyncTestArchitectur
|
||||
{
|
||||
Architecture!.AddPostRegistrationHook(a => { a.RegisterModel(new FailingModel()); });
|
||||
|
||||
await Architecture.InitializeAsync();
|
||||
Assert.ThrowsAsync<InvalidOperationException>(async () => await Architecture.InitializeAsync());
|
||||
|
||||
Assert.That(
|
||||
Architecture.CurrentPhase,
|
||||
@ -141,7 +141,7 @@ public class AsyncArchitectureTests : ArchitectureTestsBase<AsyncTestArchitectur
|
||||
a.RegisterModel(new FailingModel())
|
||||
);
|
||||
|
||||
await Architecture.InitializeAsync();
|
||||
Assert.ThrowsAsync<InvalidOperationException>(async () => await Architecture.InitializeAsync());
|
||||
|
||||
AssertInitializationFailed();
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using GFramework.Core.Abstractions.enums;
|
||||
using GFramework.Core.architecture;
|
||||
using GFramework.Core.Tests.architecture;
|
||||
@ -137,7 +136,7 @@ public class SyncArchitectureTests : ArchitectureTestsBase<SyncTestArchitecture>
|
||||
a.RegisterModel(new FailingModel())
|
||||
);
|
||||
|
||||
Architecture.Initialize();
|
||||
Assert.Throws<InvalidOperationException>(() => Architecture.Initialize());
|
||||
|
||||
AssertInitializationFailed();
|
||||
}
|
||||
|
||||
@ -134,6 +134,7 @@ public abstract class Architecture(
|
||||
|
||||
#region Lifecycle Management
|
||||
|
||||
// ==================== 方案1: 早期返回 (推荐) ====================
|
||||
/// <summary>
|
||||
/// 进入指定的架构阶段,并执行相应的生命周期管理操作
|
||||
/// </summary>
|
||||
@ -141,29 +142,57 @@ public abstract class Architecture(
|
||||
/// <exception cref="InvalidOperationException">当阶段转换不被允许时抛出异常</exception>
|
||||
protected virtual void EnterPhase(ArchitecturePhase next)
|
||||
{
|
||||
if (Configuration.ArchitectureProperties.StrictPhaseValidation &&
|
||||
(!ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) ||
|
||||
!allowed.Contains(next)))
|
||||
{
|
||||
// 验证阶段转换是否合法
|
||||
var errorMsg = $"Invalid phase transition: {CurrentPhase} -> {next}";
|
||||
_logger.Fatal(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
// 验证阶段转换
|
||||
ValidatePhaseTransition(next);
|
||||
|
||||
// 执行阶段转换
|
||||
var previousPhase = CurrentPhase;
|
||||
CurrentPhase = next;
|
||||
|
||||
if (previousPhase != next)
|
||||
_logger.Info($"Architecture phase changed: {previousPhase} -> {next}");
|
||||
|
||||
// 通知阶段变更
|
||||
NotifyPhase(next);
|
||||
NotifyPhaseAwareObjects(next);
|
||||
}
|
||||
|
||||
// 通知所有架构阶段感知对象阶段变更
|
||||
/// <summary>
|
||||
/// 验证阶段转换是否合法
|
||||
/// </summary>
|
||||
/// <param name="next">目标阶段</param>
|
||||
/// <exception cref="InvalidOperationException">当阶段转换不合法时抛出</exception>
|
||||
private void ValidatePhaseTransition(ArchitecturePhase next)
|
||||
{
|
||||
// 不需要严格验证,直接返回
|
||||
if (!Configuration.ArchitectureProperties.StrictPhaseValidation)
|
||||
return;
|
||||
|
||||
// FailedInitialization 可以从任何阶段转换,直接返回
|
||||
if (next == ArchitecturePhase.FailedInitialization)
|
||||
return;
|
||||
|
||||
// 检查转换是否在允许列表中
|
||||
if (ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) &&
|
||||
allowed.Contains(next))
|
||||
return;
|
||||
|
||||
// 转换不合法,抛出异常
|
||||
var errorMsg = $"Invalid phase transition: {CurrentPhase} -> {next}";
|
||||
_logger.Fatal(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知所有架构阶段感知对象阶段变更
|
||||
/// </summary>
|
||||
/// <param name="phase">新阶段</param>
|
||||
private void NotifyPhaseAwareObjects(ArchitecturePhase phase)
|
||||
{
|
||||
foreach (var obj in Container.GetAll<IArchitecturePhaseAware>())
|
||||
{
|
||||
_logger.Trace($"Notifying phase-aware object {obj.GetType().Name} of phase change to {next}");
|
||||
obj.OnArchitecturePhase(next);
|
||||
_logger.Trace($"Notifying phase-aware object {obj.GetType().Name} of phase change to {phase}");
|
||||
obj.OnArchitecturePhase(phase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,10 +261,11 @@ public abstract class Architecture(
|
||||
var models = _pendingInitializableList.OfType<IModel>().ToList();
|
||||
var systems = _pendingInitializableList.OfType<ISystem>().ToList();
|
||||
|
||||
// 1. 初始化工具
|
||||
// 1. 工具初始化阶段(始终进入阶段,仅在有组件时执行初始化)
|
||||
EnterPhase(ArchitecturePhase.BeforeUtilityInit);
|
||||
|
||||
if (utilities.Count != 0)
|
||||
{
|
||||
EnterPhase(ArchitecturePhase.BeforeUtilityInit);
|
||||
_logger.Info($"Initializing {utilities.Count} context utilities");
|
||||
|
||||
foreach (var utility in utilities)
|
||||
@ -244,14 +274,16 @@ public abstract class Architecture(
|
||||
await InitializeComponentAsync(utility, asyncMode);
|
||||
}
|
||||
|
||||
EnterPhase(ArchitecturePhase.AfterUtilityInit);
|
||||
_logger.Info("All context utilities initialized");
|
||||
}
|
||||
|
||||
// 2. 初始化模型
|
||||
EnterPhase(ArchitecturePhase.AfterUtilityInit);
|
||||
|
||||
// 2. 模型初始化阶段(始终进入阶段,仅在有组件时执行初始化)
|
||||
EnterPhase(ArchitecturePhase.BeforeModelInit);
|
||||
|
||||
if (models.Count != 0)
|
||||
{
|
||||
EnterPhase(ArchitecturePhase.BeforeModelInit);
|
||||
_logger.Info($"Initializing {models.Count} models");
|
||||
|
||||
foreach (var model in models)
|
||||
@ -260,14 +292,16 @@ public abstract class Architecture(
|
||||
await InitializeComponentAsync(model, asyncMode);
|
||||
}
|
||||
|
||||
EnterPhase(ArchitecturePhase.AfterModelInit);
|
||||
_logger.Info("All models initialized");
|
||||
}
|
||||
|
||||
// 3. 初始化系统
|
||||
EnterPhase(ArchitecturePhase.AfterModelInit);
|
||||
|
||||
// 3. 系统初始化阶段(始终进入阶段,仅在有组件时执行初始化)
|
||||
EnterPhase(ArchitecturePhase.BeforeSystemInit);
|
||||
|
||||
if (systems.Count != 0)
|
||||
{
|
||||
EnterPhase(ArchitecturePhase.BeforeSystemInit);
|
||||
_logger.Info($"Initializing {systems.Count} systems");
|
||||
|
||||
foreach (var system in systems)
|
||||
@ -276,10 +310,11 @@ public abstract class Architecture(
|
||||
await InitializeComponentAsync(system, asyncMode);
|
||||
}
|
||||
|
||||
EnterPhase(ArchitecturePhase.AfterSystemInit);
|
||||
_logger.Info("All systems initialized");
|
||||
}
|
||||
|
||||
EnterPhase(ArchitecturePhase.AfterSystemInit);
|
||||
|
||||
_pendingInitializableList.Clear();
|
||||
_logger.Info("All components initialized");
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.Immutable;
|
||||
using GFramework.Core.Abstractions.enums;
|
||||
|
||||
namespace GFramework.Core.architecture;
|
||||
@ -8,42 +8,47 @@ namespace GFramework.Core.architecture;
|
||||
/// </summary>
|
||||
public static class ArchitectureConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义架构阶段的线性顺序
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 架构阶段永远按照此顺序线性进行,无论是否有组件注册
|
||||
/// </remarks>
|
||||
public static readonly ArchitecturePhase[] PhaseOrder =
|
||||
[
|
||||
ArchitecturePhase.None,
|
||||
ArchitecturePhase.BeforeUtilityInit,
|
||||
ArchitecturePhase.AfterUtilityInit,
|
||||
ArchitecturePhase.BeforeModelInit,
|
||||
ArchitecturePhase.AfterModelInit,
|
||||
ArchitecturePhase.BeforeSystemInit,
|
||||
ArchitecturePhase.AfterSystemInit,
|
||||
ArchitecturePhase.Ready,
|
||||
ArchitecturePhase.Destroying,
|
||||
ArchitecturePhase.Destroyed
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// 定义架构阶段之间的有效转换关系
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 键为当前架构阶段,值为从该阶段可以转换到的下一阶段数组
|
||||
/// 架构采用线性状态机模式,只允许顺序转换,但允许从任何阶段转到 FailedInitialization
|
||||
/// </remarks>
|
||||
public static readonly ImmutableDictionary<ArchitecturePhase, ArchitecturePhase[]> PhaseTransitions =
|
||||
new Dictionary<ArchitecturePhase, ArchitecturePhase[]>
|
||||
{
|
||||
// 正常线性流程
|
||||
{ ArchitecturePhase.None, [ArchitecturePhase.BeforeUtilityInit] },
|
||||
{
|
||||
ArchitecturePhase.BeforeUtilityInit,
|
||||
[ArchitecturePhase.AfterUtilityInit, ArchitecturePhase.FailedInitialization]
|
||||
},
|
||||
{
|
||||
ArchitecturePhase.AfterUtilityInit,
|
||||
[ArchitecturePhase.BeforeModelInit, ArchitecturePhase.FailedInitialization]
|
||||
},
|
||||
{
|
||||
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.BeforeUtilityInit, [ArchitecturePhase.AfterUtilityInit] },
|
||||
{ ArchitecturePhase.AfterUtilityInit, [ArchitecturePhase.BeforeModelInit] },
|
||||
{ ArchitecturePhase.BeforeModelInit, [ArchitecturePhase.AfterModelInit] },
|
||||
{ ArchitecturePhase.AfterModelInit, [ArchitecturePhase.BeforeSystemInit] },
|
||||
{ ArchitecturePhase.BeforeSystemInit, [ArchitecturePhase.AfterSystemInit] },
|
||||
{ ArchitecturePhase.AfterSystemInit, [ArchitecturePhase.Ready] },
|
||||
{ ArchitecturePhase.Ready, [ArchitecturePhase.Destroying] },
|
||||
{ ArchitecturePhase.FailedInitialization, [ArchitecturePhase.Destroying] },
|
||||
{ ArchitecturePhase.Destroying, [ArchitecturePhase.Destroyed] }
|
||||
{ ArchitecturePhase.Destroying, [ArchitecturePhase.Destroyed] },
|
||||
// 失败路径:从任何阶段都可以转到 FailedInitialization
|
||||
{ ArchitecturePhase.FailedInitialization, [ArchitecturePhase.Destroying] }
|
||||
}.ToImmutableDictionary();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user