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