From 16fae83f703cd71648493bf5626a6ae4c85a5fc4 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sun, 5 Apr 2026 10:03:48 +0800
Subject: [PATCH 1/7] =?UTF-8?q?feat(architectures):=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=9E=B6=E6=9E=84=E5=9F=BA=E7=B1=BB=E5=92=8C=E5=88=9D=E5=A7=8B?=
=?UTF-8?q?=E5=8C=96=E7=BC=96=E6=8E=92=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 实现 Architecture 基类,提供系统、模型、工具等组件的注册与管理功能
- 添加 ArchitectureBootstrapper 协调器,负责初始化期间的基础设施准备工作
- 实现生命周期管理、组件注册管理和模块管理功能
- 提供同步和异步初始化方法,支持不同场景下的架构初始化需求
- 添加架构上下文绑定和 IOC 容器冻结功能,确保运行时依赖图稳定
- 实现架构生命周期钩子注册和阶段变更事件功能
- 添加完整的单元测试验证初始化编排流程的正确性
---
...ArchitectureInitializationPipelineTests.cs | 188 ++++++++++++++++++
GFramework.Core/Architectures/Architecture.cs | 71 ++-----
.../Architectures/ArchitectureBootstrapper.cs | 118 +++++++++++
3 files changed, 326 insertions(+), 51 deletions(-)
create mode 100644 GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
create mode 100644 GFramework.Core/Architectures/ArchitectureBootstrapper.cs
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
new file mode 100644
index 00000000..717e1b18
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
@@ -0,0 +1,188 @@
+using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Events;
+using GFramework.Core.Architectures;
+using GFramework.Core.Environment;
+using GFramework.Core.Logging;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace GFramework.Core.Tests.Architectures;
+
+///
+/// 验证 初始化编排流程的单元测试。
+/// 这些测试覆盖环境初始化、服务准备、上下文绑定和自定义服务配置的时序,
+/// 以确保核心协调器在拆分后仍保持既有行为。
+///
+[TestFixture]
+public class ArchitectureInitializationPipelineTests
+{
+ ///
+ /// 为每个测试准备独立的日志工厂和游戏上下文状态。
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+ GameContext.Clear();
+ }
+
+ ///
+ /// 清理测试期间注册的全局游戏上下文,避免跨测试污染。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ GameContext.Clear();
+ }
+
+ ///
+ /// 验证异步初始化会在执行用户初始化逻辑之前准备环境、服务和上下文。
+ ///
+ [Test]
+ public async Task InitializeAsync_Should_Prepare_Runtime_Before_OnInitialize()
+ {
+ var environment = new TrackingEnvironment();
+ var marker = new BootstrapMarker();
+ var architecture = new InitializationPipelineTestArchitecture(environment, marker);
+
+ await architecture.InitializeAsync();
+
+ AssertRuntimePrepared(architecture, environment, marker);
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证同步初始化路径复用同一套基础设施准备流程。
+ ///
+ [Test]
+ public async Task Initialize_Should_Prepare_Runtime_Before_OnInitialize()
+ {
+ var environment = new TrackingEnvironment();
+ var marker = new BootstrapMarker();
+ var architecture = new InitializationPipelineTestArchitecture(environment, marker);
+
+ architecture.Initialize();
+
+ AssertRuntimePrepared(architecture, environment, marker);
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 断言初始化阶段所需的运行时准备工作都已经完成。
+ ///
+ /// 待验证的测试架构实例。
+ /// 测试使用的环境对象。
+ /// 通过服务配置委托注册的标记服务。
+ private static void AssertRuntimePrepared(
+ InitializationPipelineTestArchitecture architecture,
+ TrackingEnvironment environment,
+ BootstrapMarker marker)
+ {
+ Assert.Multiple(() =>
+ {
+ Assert.That(architecture.ObservedEnvironmentInitialized, Is.True);
+ Assert.That(architecture.ObservedConfiguredServiceAvailable, Is.True);
+ Assert.That(architecture.ObservedEventBusAvailable, Is.True);
+ Assert.That(architecture.ObservedContextWasBound, Is.True);
+ Assert.That(architecture.ObservedEnvironmentRegistered, Is.True);
+ Assert.That(architecture.Context.GetEnvironment(), Is.SameAs(environment));
+ Assert.That(architecture.Context.GetService(), Is.SameAs(marker));
+ Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.Ready));
+ });
+ }
+
+ ///
+ /// 跟踪初始化期间关键可观察状态的测试架构。
+ ///
+ private sealed class InitializationPipelineTestArchitecture : Architecture
+ {
+ private readonly TrackingEnvironment _environment;
+ private readonly BootstrapMarker _marker;
+
+ ///
+ /// 使用可观察环境和标记服务创建测试架构。
+ ///
+ /// 用于验证初始化时序的环境对象。
+ /// 用于验证服务钩子执行结果的标记服务。
+ public InitializationPipelineTestArchitecture(
+ TrackingEnvironment environment,
+ BootstrapMarker marker)
+ : base(environment: environment)
+ {
+ _environment = environment;
+ _marker = marker;
+ }
+
+ ///
+ /// 记录用户初始化逻辑执行时环境是否已经准备完成。
+ ///
+ public bool ObservedEnvironmentInitialized { get; private set; }
+
+ ///
+ /// 记录自定义服务是否已在用户初始化前注册到容器。
+ ///
+ public bool ObservedConfiguredServiceAvailable { get; private set; }
+
+ ///
+ /// 记录内置事件总线是否已在用户初始化前可用。
+ ///
+ public bool ObservedEventBusAvailable { get; private set; }
+
+ ///
+ /// 记录当前上下文是否已在用户初始化前绑定到全局游戏上下文表。
+ ///
+ public bool ObservedContextWasBound { get; private set; }
+
+ ///
+ /// 记录环境对象是否已在用户初始化前注册到架构上下文。
+ ///
+ public bool ObservedEnvironmentRegistered { get; private set; }
+
+ ///
+ /// 为容器注册测试标记服务,用于验证初始化前的服务钩子是否执行。
+ ///
+ public override Action? Configurator => services => services.AddSingleton(_marker);
+
+ ///
+ /// 在用户初始化逻辑中采集运行时准备状态。
+ ///
+ protected override void OnInitialize()
+ {
+ ObservedEnvironmentInitialized = _environment.InitializeCallCount == 1;
+ ObservedConfiguredServiceAvailable = ReferenceEquals(Context.GetService(), _marker);
+ ObservedEventBusAvailable = Context.GetService() is not null;
+ ObservedContextWasBound = ReferenceEquals(GameContext.GetByType(GetType()), Context);
+ ObservedEnvironmentRegistered = ReferenceEquals(Context.GetEnvironment(), _environment);
+ }
+ }
+
+ ///
+ /// 用于验证环境初始化是否发生的测试环境。
+ ///
+ private sealed class TrackingEnvironment : EnvironmentBase
+ {
+ ///
+ /// 获取测试环境名称。
+ ///
+ public override string Name { get; } = "Tracking";
+
+ ///
+ /// 获取环境初始化调用次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ ///
+ /// 记录环境初始化次数。
+ ///
+ public override void Initialize()
+ {
+ InitializeCallCount++;
+ }
+ }
+
+ ///
+ /// 通过服务配置委托注册到容器的测试标记对象。
+ ///
+ private sealed class BootstrapMarker
+ {
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/Architectures/Architecture.cs b/GFramework.Core/Architectures/Architecture.cs
index c3e47436..cabffb0e 100644
--- a/GFramework.Core/Architectures/Architecture.cs
+++ b/GFramework.Core/Architectures/Architecture.cs
@@ -37,19 +37,25 @@ public abstract class Architecture : IArchitecture
IArchitectureServices? services = null,
IArchitectureContext? context = null)
{
- Configuration = configuration ?? new ArchitectureConfiguration();
- Environment = environment ?? new DefaultEnvironment();
- Services = services ?? new ArchitectureServices();
+ var resolvedConfiguration = configuration ?? new ArchitectureConfiguration();
+ var resolvedEnvironment = environment ?? new DefaultEnvironment();
+ var resolvedServices = services ?? new ArchitectureServices();
_context = context;
// 初始化 Logger
- LoggerFactoryResolver.Provider = Configuration.LoggerProperties.LoggerFactoryProvider;
+ LoggerFactoryResolver.Provider = resolvedConfiguration.LoggerProperties.LoggerFactoryProvider;
_logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name);
// 初始化管理器
- _lifecycle = new ArchitectureLifecycle(this, Configuration, Services, _logger);
- _componentRegistry = new ArchitectureComponentRegistry(this, Configuration, Services, _lifecycle, _logger);
- _modules = new ArchitectureModules(this, Services, _logger);
+ _bootstrapper = new ArchitectureBootstrapper(GetType(), resolvedEnvironment, resolvedServices, _logger);
+ _lifecycle = new ArchitectureLifecycle(this, resolvedConfiguration, resolvedServices, _logger);
+ _componentRegistry = new ArchitectureComponentRegistry(
+ this,
+ resolvedConfiguration,
+ resolvedServices,
+ _lifecycle,
+ _logger);
+ _modules = new ArchitectureModules(this, resolvedServices, _logger);
}
#endregion
@@ -70,21 +76,6 @@ public abstract class Architecture : IArchitecture
#region Properties
- ///
- /// 获取架构配置对象
- ///
- private IArchitectureConfiguration Configuration { get; }
-
- ///
- /// 获取环境配置对象
- ///
- private IEnvironment Environment { get; }
-
- ///
- /// 获取服务管理器
- ///
- private IArchitectureServices Services { get; }
-
///
/// 当前架构的阶段
///
@@ -129,6 +120,11 @@ public abstract class Architecture : IArchitecture
///
private IArchitectureContext? _context;
+ ///
+ /// 初始化基础设施编排器
+ ///
+ private readonly ArchitectureBootstrapper _bootstrapper;
+
///
/// 生命周期管理器
///
@@ -284,32 +280,7 @@ public abstract class Architecture : IArchitecture
/// 是否启用异步模式
private async Task InitializeInternalAsync(bool asyncMode)
{
- // === 基础环境初始化 ===
- Environment.Initialize();
-
- // 注册内置服务模块
- Services.ModuleManager.RegisterBuiltInModules(Services.Container);
-
- // 将 Environment 注册到容器
- if (!Services.Container.Contains())
- Services.Container.RegisterPlurality(Environment);
-
- // 初始化架构上下文
- _context ??= new ArchitectureContext(Services.Container);
- GameContext.Bind(GetType(), _context);
-
- // 为服务设置上下文
- Services.SetContext(_context);
- if (Configurator is null)
- {
- _logger.Debug("Mediator-based cqrs will not take effect without the service setter configured!");
- }
-
- // 执行服务钩子
- Services.Container.ExecuteServicesHook(Configurator);
-
- // 初始化服务模块
- await Services.ModuleManager.InitializeAllAsync(asyncMode);
+ _context = await _bootstrapper.PrepareForInitializationAsync(_context, Configurator, asyncMode);
// === 用户 OnInitialize ===
_logger.Debug("Calling user OnInitialize()");
@@ -320,9 +291,7 @@ public abstract class Architecture : IArchitecture
await _lifecycle.InitializeAllComponentsAsync(asyncMode);
// === 初始化完成阶段 ===
- Services.Container.Freeze();
- _logger.Info("IOC container frozen");
-
+ _bootstrapper.CompleteInitialization();
_lifecycle.MarkAsReady();
_logger.Info($"Architecture {GetType().Name} is ready - all components initialized");
}
diff --git a/GFramework.Core/Architectures/ArchitectureBootstrapper.cs b/GFramework.Core/Architectures/ArchitectureBootstrapper.cs
new file mode 100644
index 00000000..984c0a07
--- /dev/null
+++ b/GFramework.Core/Architectures/ArchitectureBootstrapper.cs
@@ -0,0 +1,118 @@
+using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Environment;
+using GFramework.Core.Abstractions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace GFramework.Core.Architectures;
+
+///
+/// 协调架构初始化期间的基础设施准备工作。
+/// 该类型将环境初始化、服务模块启动、上下文绑定和服务容器配置从 中拆出,
+/// 使核心架构类只保留生命周期入口和公共 API 协调职责。
+///
+internal sealed class ArchitectureBootstrapper(
+ Type architectureType,
+ IEnvironment environment,
+ IArchitectureServices services,
+ ILogger logger)
+{
+ ///
+ /// 在执行用户 OnInitialize 之前准备架构运行时。
+ /// 该流程必须保证环境、内置服务、上下文和服务钩子已经可用,
+ /// 因为用户初始化逻辑通常会立即访问事件总线、查询执行器或环境对象。
+ ///
+ /// 调用方已经提供的上下文;如果为空则创建默认上下文。
+ /// 可选的容器配置委托,用于接入 Mediator 等扩展服务。
+ /// 是否以异步模式初始化服务模块。
+ /// 已绑定到当前架构类型的架构上下文。
+ public async Task PrepareForInitializationAsync(
+ IArchitectureContext? existingContext,
+ Action? configurator,
+ bool asyncMode)
+ {
+ InitializeEnvironment();
+ RegisterBuiltInModules();
+ EnsureEnvironmentRegistered();
+
+ var context = EnsureContext(existingContext);
+ ConfigureServices(context, configurator);
+ await InitializeServiceModulesAsync(asyncMode);
+ return context;
+ }
+
+ ///
+ /// 完成用户组件初始化之后的收尾工作。
+ /// 冻结容器可以阻止 Ready 阶段之后的意外服务注册,保持运行时依赖图稳定。
+ ///
+ public void CompleteInitialization()
+ {
+ services.Container.Freeze();
+ logger.Info("IOC container frozen");
+ }
+
+ ///
+ /// 初始化运行环境,使环境对象在后续服务构建和用户初始化前进入可用状态。
+ ///
+ private void InitializeEnvironment()
+ {
+ environment.Initialize();
+ }
+
+ ///
+ /// 注册框架内置服务模块。
+ /// 该步骤必须先于执行服务钩子,以便容器具备 CQRS 和事件总线等基础服务。
+ ///
+ private void RegisterBuiltInModules()
+ {
+ services.ModuleManager.RegisterBuiltInModules(services.Container);
+ }
+
+ ///
+ /// 确保环境对象可以通过架构容器解析。
+ /// 如果调用方已经预先注册了自定义环境实例,则保留现有绑定,避免覆盖外部配置。
+ ///
+ private void EnsureEnvironmentRegistered()
+ {
+ if (!services.Container.Contains())
+ services.Container.RegisterPlurality(environment);
+ }
+
+ ///
+ /// 获取本次初始化使用的架构上下文,并将其绑定到全局游戏上下文表。
+ /// 绑定发生在用户初始化之前,确保组件在注册阶段即可通过架构类型解析上下文。
+ ///
+ /// 外部提供的上下文。
+ /// 实际用于本次初始化的上下文实例。
+ private IArchitectureContext EnsureContext(IArchitectureContext? existingContext)
+ {
+ var context = existingContext ?? new ArchitectureContext(services.Container);
+ GameContext.Bind(architectureType, context);
+ return context;
+ }
+
+ ///
+ /// 为服务容器设置上下文并执行扩展配置钩子。
+ /// 这一步统一承接 Mediator 等容器扩展的接入点,避免 直接操作容器细节。
+ ///
+ /// 当前架构上下文。
+ /// 可选的服务集合配置委托。
+ private void ConfigureServices(IArchitectureContext context, Action? configurator)
+ {
+ services.SetContext(context);
+
+ if (configurator is null)
+ logger.Debug("Mediator-based cqrs will not take effect without the service setter configured!");
+
+ services.Container.ExecuteServicesHook(configurator);
+ }
+
+ ///
+ /// 初始化所有服务模块。
+ /// 该过程在用户注册系统、模型和工具之前完成,避免组件在初始化期间访问未准备好的服务。
+ ///
+ /// 是否允许异步初始化服务模块。
+ private async Task InitializeServiceModulesAsync(bool asyncMode)
+ {
+ await services.ModuleManager.InitializeAllAsync(asyncMode);
+ }
+}
\ No newline at end of file
From 01dc1523a52068948a85ab20405cec740ba24043 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sun, 5 Apr 2026 10:52:21 +0800
Subject: [PATCH 2/7] =?UTF-8?q?feat(architecture):=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=9E=B6=E6=9E=84=E6=A0=B8=E5=BF=83=E7=BB=84=E4=BB=B6=E5=92=8C?=
=?UTF-8?q?=E4=BE=9D=E8=B5=96=E6=B3=A8=E5=85=A5=E5=AE=B9=E5=99=A8=E5=AE=9E?=
=?UTF-8?q?=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 实现 Architecture 基类,提供系统、模型、工具等组件的注册与管理功能
- 添加 ArchitectureComponentRegistry 组件注册管理器,负责管理系统、模型、工具的注册
- 实现 ArchitectureLifecycle 生命周期管理器,管理架构阶段转换和组件初始化
- 添加 ArchitectureModules 模块管理器,负责架构模块安装和中介行为注册
- 实现 MicrosoftDiContainer 依赖注入容器,包装 Microsoft.Extensions.DependencyInjection
- 提供完整的组件生命周期管理,支持同步和异步初始化模式
- 添加架构阶段管理和组件注册验证机制
---
.../Architectures/IArchitecture.cs | 4 +-
...hitectureComponentRegistryBehaviorTests.cs | 306 ++++++++++++++++++
.../ArchitectureLifecycleBehaviorTests.cs | 253 +++++++++++++++
.../ArchitectureModulesBehaviorTests.cs | 188 +++++++++++
GFramework.Core/Architectures/Architecture.cs | 4 +-
.../ArchitectureComponentRegistry.cs | 2 +
.../Architectures/ArchitectureDisposer.cs | 111 +++++++
.../Architectures/ArchitectureLifecycle.cs | 211 ++----------
.../Architectures/ArchitectureModules.cs | 3 +-
.../ArchitecturePhaseCoordinator.cs | 116 +++++++
GFramework.Core/Ioc/MicrosoftDiContainer.cs | 37 ++-
11 files changed, 1046 insertions(+), 189 deletions(-)
create mode 100644 GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
create mode 100644 GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
create mode 100644 GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
create mode 100644 GFramework.Core/Architectures/ArchitectureDisposer.cs
create mode 100644 GFramework.Core/Architectures/ArchitecturePhaseCoordinator.cs
diff --git a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs
index c2ba8fd6..0055d3fe 100644
--- a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs
+++ b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs
@@ -74,7 +74,9 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia
///
/// 注册中介行为管道
- /// 用于配置Mediator框架的行为拦截和处理逻辑
+ /// 用于配置Mediator框架的行为拦截和处理逻辑。
+ /// 既支持实现 IPipelineBehavior<,> 的开放泛型行为类型,
+ /// 也支持绑定到单一请求/响应对的封闭行为类型。
///
/// 行为类型,必须是引用类型
void RegisterMediatorBehavior()
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
new file mode 100644
index 00000000..74344191
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
@@ -0,0 +1,306 @@
+using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Model;
+using GFramework.Core.Abstractions.Systems;
+using GFramework.Core.Abstractions.Utility;
+using GFramework.Core.Architectures;
+using GFramework.Core.Logging;
+
+namespace GFramework.Core.Tests.Architectures;
+
+///
+/// 验证 Architecture 通过 ArchitectureComponentRegistry 暴露出的组件注册行为。
+/// 这些测试覆盖实例注册、工厂注册、上下文注入、生命周期初始化和 Ready 后注册约束,
+/// 用于保护组件注册器在继续重构后的既有契约。
+///
+[TestFixture]
+public class ArchitectureComponentRegistryBehaviorTests
+{
+ ///
+ /// 初始化日志工厂和全局上下文状态。
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+ GameContext.Clear();
+ }
+
+ ///
+ /// 清理测试过程中绑定到全局表的架构上下文。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ GameContext.Clear();
+ }
+
+ ///
+ /// 验证系统实例注册会注入上下文并参与生命周期初始化。
+ ///
+ [Test]
+ public async Task RegisterSystem_Instance_Should_Set_Context_And_Initialize_System()
+ {
+ var system = new TrackingSystem();
+ var architecture = new RegistryTestArchitecture(target => target.RegisterSystem(system));
+
+ await architecture.InitializeAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(system.GetContext(), Is.SameAs(architecture.Context));
+ Assert.That(system.InitializeCallCount, Is.EqualTo(1));
+ Assert.That(architecture.Context.GetSystem(), Is.SameAs(system));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证模型实例注册会注入上下文并参与生命周期初始化。
+ ///
+ [Test]
+ public async Task RegisterModel_Instance_Should_Set_Context_And_Initialize_Model()
+ {
+ var model = new TrackingModel();
+ var architecture = new RegistryTestArchitecture(target => target.RegisterModel(model));
+
+ await architecture.InitializeAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(model.GetContext(), Is.SameAs(architecture.Context));
+ Assert.That(model.InitializeCallCount, Is.EqualTo(1));
+ Assert.That(architecture.Context.GetModel(), Is.SameAs(model));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证上下文工具注册会注入上下文并参与生命周期初始化。
+ ///
+ [Test]
+ public async Task RegisterUtility_Instance_Should_Set_Context_For_ContextUtility()
+ {
+ var utility = new TrackingContextUtility();
+ var architecture = new RegistryTestArchitecture(target => target.RegisterUtility(utility));
+
+ await architecture.InitializeAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(utility.GetContext(), Is.SameAs(architecture.Context));
+ Assert.That(utility.InitializeCallCount, Is.EqualTo(1));
+ Assert.That(architecture.Context.GetUtility(), Is.SameAs(utility));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证普通工具的工厂注册会在首次解析时创建单例并执行创建回调。
+ ///
+ [Test]
+ public async Task RegisterUtility_Type_Should_Create_Singleton_And_Invoke_Callback()
+ {
+ FactoryCreatedUtility? callbackInstance = null;
+ var architecture = new RegistryTestArchitecture(target =>
+ target.RegisterUtility(created => callbackInstance = created));
+
+ await architecture.InitializeAsync();
+
+ var first = architecture.Context.GetUtility();
+ var second = architecture.Context.GetUtility();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(callbackInstance, Is.SameAs(first));
+ Assert.That(second, Is.SameAs(first));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证 Ready 阶段后不允许继续注册 Utility,保持与系统和模型一致的约束。
+ ///
+ [Test]
+ public async Task RegisterUtility_After_Ready_Should_Throw_InvalidOperationException()
+ {
+ var architecture = new RegistryTestArchitecture(_ => { });
+ await architecture.InitializeAsync();
+
+ Assert.That(
+ () => architecture.RegisterUtility(new TrackingContextUtility()),
+ Throws.InvalidOperationException.With.Message.EqualTo(
+ "Cannot register utility after Architecture is Ready"));
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 用于测试组件注册行为的最小架构实现。
+ ///
+ private sealed class RegistryTestArchitecture(Action registrationAction) : Architecture
+ {
+ ///
+ /// 在初始化阶段执行测试注入的注册逻辑。
+ ///
+ protected override void OnInitialize()
+ {
+ registrationAction(this);
+ }
+ }
+
+ ///
+ /// 记录初始化与上下文注入情况的测试系统。
+ ///
+ private sealed class TrackingSystem : ISystem
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取系统初始化调用次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ ///
+ /// 记录初始化调用。
+ ///
+ public void Initialize()
+ {
+ InitializeCallCount++;
+ }
+
+ ///
+ /// 该测试系统不关心阶段变更。
+ ///
+ /// 当前架构阶段。
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ ///
+ /// 存储注入的架构上下文。
+ ///
+ /// 架构上下文。
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ ///
+ /// 返回当前持有的架构上下文。
+ ///
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+
+ ///
+ /// 该测试系统没有额外销毁逻辑。
+ ///
+ public void Destroy()
+ {
+ }
+ }
+
+ ///
+ /// 记录初始化与上下文注入情况的测试模型。
+ ///
+ private sealed class TrackingModel : IModel
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取模型初始化调用次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ ///
+ /// 记录初始化调用。
+ ///
+ public void Initialize()
+ {
+ InitializeCallCount++;
+ }
+
+ ///
+ /// 该测试模型不关心阶段变更。
+ ///
+ /// 当前架构阶段。
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ ///
+ /// 存储注入的架构上下文。
+ ///
+ /// 架构上下文。
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ ///
+ /// 返回当前持有的架构上下文。
+ ///
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 记录初始化与上下文注入情况的测试上下文工具。
+ ///
+ private sealed class TrackingContextUtility : IContextUtility
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取工具初始化调用次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ ///
+ /// 记录初始化调用。
+ ///
+ public void Initialize()
+ {
+ InitializeCallCount++;
+ }
+
+ ///
+ /// 存储注入的架构上下文。
+ ///
+ /// 架构上下文。
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ ///
+ /// 返回当前持有的架构上下文。
+ ///
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+
+ ///
+ /// 该测试工具没有额外销毁逻辑。
+ ///
+ public void Destroy()
+ {
+ }
+ }
+
+ ///
+ /// 用于验证普通工厂注册路径的简单工具。
+ ///
+ private sealed class FactoryCreatedUtility : IUtility
+ {
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
new file mode 100644
index 00000000..0bde4b5d
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
@@ -0,0 +1,253 @@
+using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Lifecycle;
+using GFramework.Core.Abstractions.Model;
+using GFramework.Core.Abstractions.Systems;
+using GFramework.Core.Abstractions.Utility;
+using GFramework.Core.Architectures;
+using GFramework.Core.Logging;
+
+namespace GFramework.Core.Tests.Architectures;
+
+///
+/// 验证 Architecture 生命周期行为的集成测试。
+/// 这些测试覆盖阶段流转、失败状态传播和逆序销毁规则,
+/// 用于保护拆分后的生命周期管理、阶段协调与销毁协调行为。
+///
+[TestFixture]
+public class ArchitectureLifecycleBehaviorTests
+{
+ ///
+ /// 为每个测试准备独立的日志工厂和全局上下文状态。
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+ GameContext.Clear();
+ }
+
+ ///
+ /// 清理测试注册到全局上下文表的架构上下文。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ GameContext.Clear();
+ }
+
+ ///
+ /// 验证初始化流程会按既定顺序推进所有生命周期阶段。
+ ///
+ [Test]
+ public async Task InitializeAsync_Should_Enter_Expected_Phases_In_Order()
+ {
+ var architecture = new PhaseTrackingArchitecture();
+
+ await architecture.InitializeAsync();
+
+ Assert.That(architecture.PhaseHistory, Is.EqualTo(new[]
+ {
+ ArchitecturePhase.BeforeUtilityInit,
+ ArchitecturePhase.AfterUtilityInit,
+ ArchitecturePhase.BeforeModelInit,
+ ArchitecturePhase.AfterModelInit,
+ ArchitecturePhase.BeforeSystemInit,
+ ArchitecturePhase.AfterSystemInit,
+ ArchitecturePhase.Ready
+ }));
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证用户初始化失败时,等待 Ready 的任务会失败并进入 FailedInitialization 阶段。
+ ///
+ [Test]
+ public async Task InitializeAsync_When_OnInitialize_Throws_Should_Mark_FailedInitialization()
+ {
+ var architecture = new PhaseTrackingArchitecture(() => throw new InvalidOperationException("boom"));
+
+ var exception = Assert.ThrowsAsync(async () => await architecture.InitializeAsync());
+ Assert.That(exception, Is.Not.Null);
+ Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.FailedInitialization));
+ Assert.ThrowsAsync(async () => await architecture.WaitUntilReadyAsync());
+ }
+
+ ///
+ /// 验证销毁流程会按注册逆序释放组件,并推进 Destroying/Destroyed 阶段。
+ ///
+ [Test]
+ public async Task DestroyAsync_Should_Destroy_Components_In_Reverse_Registration_Order()
+ {
+ var destroyOrder = new List();
+ var architecture = new DestroyOrderArchitecture(destroyOrder);
+
+ await architecture.InitializeAsync();
+ await architecture.DestroyAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(destroyOrder, Is.EqualTo(new[] { "system", "model", "utility" }));
+ Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.Destroyed));
+ Assert.That(architecture.PhaseHistory[^2..], Is.EqualTo(new[]
+ {
+ ArchitecturePhase.Destroying,
+ ArchitecturePhase.Destroyed
+ }));
+ });
+ }
+
+ ///
+ /// 记录阶段流转的可配置测试架构。
+ ///
+ private sealed class PhaseTrackingArchitecture : Architecture
+ {
+ private readonly Action? _onInitializeAction;
+
+ ///
+ /// 创建一个可选地在用户初始化阶段执行自定义逻辑的测试架构。
+ ///
+ /// 用户初始化时执行的测试回调。
+ public PhaseTrackingArchitecture(Action? onInitializeAction = null)
+ {
+ _onInitializeAction = onInitializeAction;
+ PhaseChanged += phase => PhaseHistory.Add(phase);
+ }
+
+ ///
+ /// 获取架构经历过的阶段列表。
+ ///
+ public List PhaseHistory { get; } = [];
+
+ ///
+ /// 执行测试注入的初始化逻辑。
+ ///
+ protected override void OnInitialize()
+ {
+ _onInitializeAction?.Invoke();
+ }
+ }
+
+ ///
+ /// 在初始化时注册可销毁组件的测试架构。
+ ///
+ private sealed class DestroyOrderArchitecture : Architecture
+ {
+ private readonly List _destroyOrder;
+
+ ///
+ /// 创建用于验证销毁顺序的测试架构。
+ ///
+ /// 记录组件销毁顺序的列表。
+ public DestroyOrderArchitecture(List destroyOrder)
+ {
+ _destroyOrder = destroyOrder;
+ PhaseChanged += phase => PhaseHistory.Add(phase);
+ }
+
+ ///
+ /// 获取架构经历过的阶段列表。
+ ///
+ public List PhaseHistory { get; } = [];
+
+ ///
+ /// 注册会记录销毁顺序的 Utility、Model 和 System。
+ ///
+ protected override void OnInitialize()
+ {
+ RegisterUtility(new TrackingDestroyableUtility(_destroyOrder));
+ RegisterModel(new TrackingDestroyableModel(_destroyOrder));
+ RegisterSystem(new TrackingDestroyableSystem(_destroyOrder));
+ }
+ }
+
+ ///
+ /// 用于验证逆序销毁的上下文工具。
+ ///
+ private sealed class TrackingDestroyableUtility(List destroyOrder) : IContextUtility
+ {
+ private IArchitectureContext _context = null!;
+
+ public void Initialize()
+ {
+ }
+
+ public void Destroy()
+ {
+ destroyOrder.Add("utility");
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于验证逆序销毁的模型。
+ ///
+ private sealed class TrackingDestroyableModel(List destroyOrder) : IModel, IDestroyable
+ {
+ private IArchitectureContext _context = null!;
+
+ public void Destroy()
+ {
+ destroyOrder.Add("model");
+ }
+
+ public void Initialize()
+ {
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于验证逆序销毁的系统。
+ ///
+ private sealed class TrackingDestroyableSystem(List destroyOrder) : ISystem
+ {
+ private IArchitectureContext _context = null!;
+
+ public void Initialize()
+ {
+ }
+
+ public void Destroy()
+ {
+ destroyOrder.Add("system");
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
new file mode 100644
index 00000000..05601230
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
@@ -0,0 +1,188 @@
+using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Utility;
+using GFramework.Core.Architectures;
+using GFramework.Core.Logging;
+using Mediator;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace GFramework.Core.Tests.Architectures;
+
+///
+/// 验证 Architecture 通过 ArchitectureModules 暴露出的模块安装与 Mediator 行为注册能力。
+/// 这些测试覆盖模块安装回调和中介管道行为接入,确保模块管理器仍然保持可观察行为不变。
+///
+[TestFixture]
+public class ArchitectureModulesBehaviorTests
+{
+ ///
+ /// 初始化日志工厂和全局上下文状态。
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+ GameContext.Clear();
+ TrackingPipelineBehavior.InvocationCount = 0;
+ }
+
+ ///
+ /// 清理测试过程中写入的全局上下文状态。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ GameContext.Clear();
+ TrackingPipelineBehavior.InvocationCount = 0;
+ }
+
+ ///
+ /// 验证安装模块时会把当前架构实例传给模块,并允许模块在安装阶段注册组件。
+ ///
+ [Test]
+ public async Task InstallModule_Should_Invoke_Module_Install_With_Current_Architecture()
+ {
+ var module = new TrackingArchitectureModule();
+ var architecture = new ModuleTestArchitecture(target => target.InstallModule(module));
+
+ await architecture.InitializeAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(module.InstalledArchitecture, Is.SameAs(architecture));
+ Assert.That(module.InstallCallCount, Is.EqualTo(1));
+ Assert.That(architecture.Context.GetUtility(), Is.Not.Null);
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证注册的 Mediator 行为会参与请求管道执行。
+ ///
+ [Test]
+ public async Task RegisterMediatorBehavior_Should_Apply_Pipeline_Behavior_To_Request()
+ {
+ var architecture = new ModuleTestArchitecture(target =>
+ target.RegisterMediatorBehavior>());
+
+ await architecture.InitializeAsync();
+
+ var response = await architecture.Context.SendRequestAsync(new ModuleBehaviorRequest());
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(response, Is.EqualTo("handled"));
+ Assert.That(TrackingPipelineBehavior.InvocationCount, Is.EqualTo(1));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 用于测试模块行为的最小架构实现。
+ ///
+ private sealed class ModuleTestArchitecture(Action registrationAction) : Architecture
+ {
+ ///
+ /// 打开 Mediator 服务注册,以便测试中介行为接入。
+ ///
+ public override Action? Configurator =>
+ services => services.AddMediator(options => { options.ServiceLifetime = ServiceLifetime.Singleton; });
+
+ ///
+ /// 在初始化阶段执行测试注入的模块注册逻辑。
+ ///
+ protected override void OnInitialize()
+ {
+ registrationAction(this);
+ }
+ }
+
+ ///
+ /// 记录模块安装调用情况的测试模块。
+ ///
+ private sealed class TrackingArchitectureModule : IArchitectureModule
+ {
+ ///
+ /// 获取模块安装调用次数。
+ ///
+ public int InstallCallCount { get; private set; }
+
+ ///
+ /// 获取最近一次接收到的架构实例。
+ ///
+ public IArchitecture? InstalledArchitecture { get; private set; }
+
+ ///
+ /// 记录安装调用,并在安装阶段注册一个工具验证调用链可用。
+ ///
+ /// 目标架构实例。
+ public void Install(IArchitecture architecture)
+ {
+ InstallCallCount++;
+ InstalledArchitecture = architecture;
+ architecture.RegisterUtility(new InstalledByModuleUtility());
+ }
+ }
+
+ ///
+ /// 由测试模块安装时注册的简单工具。
+ ///
+ private sealed class InstalledByModuleUtility : IUtility
+ {
+ }
+}
+
+///
+/// 用于验证管道行为注册是否生效的测试请求。
+///
+public sealed class ModuleBehaviorRequest : IRequest
+{
+}
+
+///
+/// 处理测试请求的处理器。
+///
+public sealed class ModuleBehaviorRequestHandler : IRequestHandler
+{
+ ///
+ /// 返回固定结果,便于聚焦验证管道行为是否执行。
+ ///
+ /// 请求实例。
+ /// 取消令牌。
+ /// 固定响应内容。
+ public ValueTask Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken)
+ {
+ return ValueTask.FromResult("handled");
+ }
+}
+
+///
+/// 记录请求通过管道次数的测试行为。
+///
+/// 请求类型。
+/// 响应类型。
+public sealed class TrackingPipelineBehavior : IPipelineBehavior
+ where TRequest : IRequest
+{
+ ///
+ /// 获取当前测试进程中该请求类型对应的行为触发次数。
+ ///
+ public static int InvocationCount { get; set; }
+
+ ///
+ /// 记录一次行为执行,然后继续执行下一个处理器。
+ ///
+ /// 当前请求消息。
+ /// 下一个处理委托。
+ /// 取消令牌。
+ /// 下游处理器的响应结果。
+ public async ValueTask Handle(
+ TRequest message,
+ MessageHandlerDelegate next,
+ CancellationToken cancellationToken)
+ {
+ InvocationCount++;
+ return await next(message, cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/Architectures/Architecture.cs b/GFramework.Core/Architectures/Architecture.cs
index cabffb0e..af96d03f 100644
--- a/GFramework.Core/Architectures/Architecture.cs
+++ b/GFramework.Core/Architectures/Architecture.cs
@@ -16,6 +16,7 @@ namespace GFramework.Core.Architectures;
/// 专注于生命周期管理、初始化流程控制和架构阶段转换。
///
/// 重构说明:此类已重构为协调器模式,将职责委托给专门的管理器:
+/// - ArchitectureBootstrapper: 初始化基础设施编排
/// - ArchitectureLifecycle: 生命周期管理
/// - ArchitectureComponentRegistry: 组件注册管理
/// - ArchitectureModules: 模块管理
@@ -146,7 +147,8 @@ public abstract class Architecture : IArchitecture
///
/// 注册中介行为管道
- /// 用于配置Mediator框架的行为拦截和处理逻辑
+ /// 用于配置Mediator框架的行为拦截和处理逻辑。
+ /// 可以传入开放泛型行为类型,也可以传入绑定到特定请求的封闭行为类型。
///
/// 行为类型,必须是引用类型
public void RegisterMediatorBehavior() where TBehavior : class
diff --git a/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs b/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
index d39d5972..91b2a846 100644
--- a/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
+++ b/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
@@ -155,6 +155,7 @@ internal sealed class ArchitectureComponentRegistry(
/// 注册成功的工具实例
public TUtility RegisterUtility(TUtility utility) where TUtility : IUtility
{
+ ValidateRegistration("utility");
logger.Debug($"Registering utility: {typeof(TUtility).Name}");
// 处理上下文工具类型的设置和生命周期管理
@@ -177,6 +178,7 @@ internal sealed class ArchitectureComponentRegistry(
/// 可选的实例创建后回调
public void RegisterUtility(Action? onCreated = null) where T : class, IUtility
{
+ ValidateRegistration("utility");
logger.Debug($"Registering utility type: {typeof(T).Name}");
services.Container.RegisterFactory(sp =>
diff --git a/GFramework.Core/Architectures/ArchitectureDisposer.cs b/GFramework.Core/Architectures/ArchitectureDisposer.cs
new file mode 100644
index 00000000..1c1a861d
--- /dev/null
+++ b/GFramework.Core/Architectures/ArchitectureDisposer.cs
@@ -0,0 +1,111 @@
+using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Lifecycle;
+using GFramework.Core.Abstractions.Logging;
+
+namespace GFramework.Core.Architectures;
+
+///
+/// 统一处理架构内可销毁对象的登记与释放。
+/// 该类型封装逆序销毁、异常隔离和服务模块清理规则,
+/// 让 可以专注于初始化流程本身。
+///
+internal sealed class ArchitectureDisposer(
+ IArchitectureServices services,
+ ILogger logger)
+{
+ ///
+ /// 保留注册顺序的可销毁对象列表。
+ /// 销毁时按逆序遍历,以尽量匹配组件间的依赖方向。
+ ///
+ private readonly List