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..583c30c8
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
@@ -0,0 +1,717 @@
+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;
+using Microsoft.Extensions.DependencyInjection;
+
+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();
+ }
+
+ ///
+ /// 验证系统类型注册会在初始化期间物化实例、注入构造函数依赖并执行创建回调。
+ ///
+ [Test]
+ public async Task RegisterSystem_Type_Should_Create_Instance_During_Initialization()
+ {
+ var dependency = new ConstructorDependency("system-dependency");
+ FactoryCreatedSystem? callbackInstance = null;
+ var architecture = new RegistryTestArchitecture(
+ target => target.RegisterSystem(created => callbackInstance = created),
+ services => services.AddSingleton(dependency));
+
+ await architecture.InitializeAsync();
+
+ var resolved = architecture.Context.GetSystem();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(callbackInstance, Is.Not.Null);
+ Assert.That(resolved, Is.SameAs(callbackInstance));
+ Assert.That(resolved.Dependency, Is.SameAs(dependency));
+ Assert.That(resolved.GetContext(), Is.SameAs(architecture.Context));
+ Assert.That(resolved.InitializeCallCount, Is.EqualTo(1));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证模型类型注册会在初始化期间物化实例、注入构造函数依赖并执行创建回调。
+ ///
+ [Test]
+ public async Task RegisterModel_Type_Should_Create_Instance_During_Initialization()
+ {
+ var dependency = new ConstructorDependency("model-dependency");
+ FactoryCreatedModel? callbackInstance = null;
+ var architecture = new RegistryTestArchitecture(
+ target => target.RegisterModel(created => callbackInstance = created),
+ services => services.AddSingleton(dependency));
+
+ await architecture.InitializeAsync();
+
+ var resolved = architecture.Context.GetModel();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(callbackInstance, Is.Not.Null);
+ Assert.That(resolved, Is.SameAs(callbackInstance));
+ Assert.That(resolved.Dependency, Is.SameAs(dependency));
+ Assert.That(resolved.GetContext(), Is.SameAs(architecture.Context));
+ Assert.That(resolved.InitializeCallCount, Is.EqualTo(1));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证预冻结阶段通过实现类型注册的单例依赖会在同一轮组件激活中复用同一个实例。
+ /// 该回归测试用于保护 的共享单例缓存,避免系统和模型分别创建重复单例。
+ ///
+ [Test]
+ public async Task RegisterSystem_And_Model_Type_Should_Reuse_ImplementationType_Singleton_During_Activation()
+ {
+ var counter = new DependencyConstructionCounter();
+ var architecture = new RegistryTestArchitecture(
+ target =>
+ {
+ target.RegisterSystem();
+ target.RegisterModel();
+ },
+ services =>
+ {
+ services.AddSingleton(counter);
+ services.AddSingleton();
+ });
+
+ await architecture.InitializeAsync();
+
+ var system = architecture.Context.GetSystem();
+ var model = architecture.Context.GetModel();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(counter.CreationCount, Is.EqualTo(1));
+ Assert.That(system.Dependency, Is.SameAs(model.Dependency));
+ });
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 验证预冻结阶段通过工厂注册的单例依赖会在同一轮组件激活中复用同一个实例。
+ /// 该回归测试覆盖 ImplementationFactory 描述符路径,避免用户工厂在初始化时被重复调用。
+ ///
+ [Test]
+ public async Task RegisterSystem_And_Model_Type_Should_Reuse_Factory_Singleton_During_Activation()
+ {
+ var creationCount = 0;
+ var architecture = new RegistryTestArchitecture(
+ target =>
+ {
+ target.RegisterSystem();
+ target.RegisterModel();
+ },
+ services =>
+ {
+ services.AddSingleton(_ =>
+ {
+ creationCount++;
+ return new FactorySharedDependency();
+ });
+ });
+
+ await architecture.InitializeAsync();
+
+ var system = architecture.Context.GetSystem();
+ var model = architecture.Context.GetModel();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(creationCount, Is.EqualTo(1));
+ Assert.That(system.Dependency, Is.SameAs(model.Dependency));
+ });
+
+ 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 : Architecture
+ {
+ private readonly Action? _configurator;
+ private readonly Action _registrationAction;
+
+ ///
+ /// 创建一个可选地附带服务配置逻辑的测试架构。
+ ///
+ /// 初始化阶段执行的组件注册逻辑。
+ /// 初始化前执行的服务配置逻辑。
+ public RegistryTestArchitecture(
+ Action registrationAction,
+ Action? configurator = null)
+ {
+ _registrationAction = registrationAction;
+ _configurator = configurator;
+ }
+
+ ///
+ /// 返回测试注入的服务配置逻辑。
+ ///
+ public override Action? Configurator => _configurator;
+
+ ///
+ /// 在初始化阶段执行测试注入的注册逻辑。
+ ///
+ 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
+ {
+ }
+
+ ///
+ /// 用于验证构造函数依赖注入的简单依赖对象。
+ ///
+ private sealed class ConstructorDependency(string name)
+ {
+ ///
+ /// 获取依赖对象名称。
+ ///
+ public string Name { get; } = name;
+ }
+
+ ///
+ /// 用于验证系统类型注册路径的工厂创建系统。
+ ///
+ private sealed class FactoryCreatedSystem(ConstructorDependency dependency) : ISystem
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的依赖对象。
+ ///
+ public ConstructorDependency Dependency { get; } = dependency;
+
+ ///
+ /// 获取初始化调用次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ public void Initialize()
+ {
+ InitializeCallCount++;
+ }
+
+ public void Destroy()
+ {
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于验证模型类型注册路径的工厂创建模型。
+ ///
+ private sealed class FactoryCreatedModel(ConstructorDependency dependency) : IModel
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的依赖对象。
+ ///
+ public ConstructorDependency Dependency { get; } = dependency;
+
+ ///
+ /// 获取初始化调用次数。
+ ///
+ 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 DependencyConstructionCounter
+ {
+ ///
+ /// 获取共享依赖被构造的次数。
+ ///
+ public int CreationCount { get; private set; }
+
+ ///
+ /// 记录一次新的依赖构造。
+ ///
+ public void RecordCreation()
+ {
+ CreationCount++;
+ }
+ }
+
+ ///
+ /// 用于覆盖 ImplementationType 单例描述符路径的共享依赖。
+ ///
+ private sealed class ImplementationTypeSharedDependency
+ {
+ ///
+ /// 创建共享依赖并记录构造次数。
+ ///
+ /// 用于统计构造次数的计数器。
+ public ImplementationTypeSharedDependency(DependencyConstructionCounter counter)
+ {
+ counter.RecordCreation();
+ }
+ }
+
+ ///
+ /// 用于覆盖 ImplementationType 单例复用路径的测试系统。
+ ///
+ private sealed class ImplementationTypeDependencySystem(ImplementationTypeSharedDependency dependency) : ISystem
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的共享依赖。
+ ///
+ public ImplementationTypeSharedDependency Dependency { get; } = dependency;
+
+ public void Initialize()
+ {
+ }
+
+ public void Destroy()
+ {
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于覆盖 ImplementationType 单例复用路径的测试模型。
+ ///
+ private sealed class ImplementationTypeDependencyModel(ImplementationTypeSharedDependency dependency) : IModel
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的共享依赖。
+ ///
+ public ImplementationTypeSharedDependency Dependency { get; } = dependency;
+
+ public void Initialize()
+ {
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于覆盖 ImplementationFactory 单例描述符路径的共享依赖。
+ ///
+ private sealed class FactorySharedDependency
+ {
+ }
+
+ ///
+ /// 用于覆盖 ImplementationFactory 单例复用路径的测试系统。
+ ///
+ private sealed class FactoryDependencySystem(FactorySharedDependency dependency) : ISystem
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的共享依赖。
+ ///
+ public FactorySharedDependency Dependency { get; } = dependency;
+
+ public void Initialize()
+ {
+ }
+
+ public void Destroy()
+ {
+ }
+
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ }
+
+ public void SetContext(IArchitectureContext context)
+ {
+ _context = context;
+ }
+
+ public IArchitectureContext GetContext()
+ {
+ return _context;
+ }
+ }
+
+ ///
+ /// 用于覆盖 ImplementationFactory 单例复用路径的测试模型。
+ ///
+ private sealed class FactoryDependencyModel(FactorySharedDependency dependency) : IModel
+ {
+ private IArchitectureContext _context = null!;
+
+ ///
+ /// 获取构造函数注入的共享依赖。
+ ///
+ public FactorySharedDependency Dependency { get; } = dependency;
+
+ public void Initialize()
+ {
+ }
+
+ 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/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.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
new file mode 100644
index 00000000..b0ef7262
--- /dev/null
+++ b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
@@ -0,0 +1,463 @@
+using System.Reflection;
+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;
+using Microsoft.Extensions.DependencyInjection;
+
+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
+ }));
+ });
+ }
+
+ ///
+ /// 验证初始化失败后仍然允许执行销毁流程。
+ /// 该回归测试用于保护 FailedInitialization → Destroying 的合法迁移,避免失败路径上的组件与容器泄漏。
+ ///
+ [Test]
+ public async Task DestroyAsync_After_FailedInitialization_Should_Cleanup_And_Enter_Destroyed()
+ {
+ var destroyOrder = new List();
+ var architecture = new FailingInitializationArchitecture(destroyOrder);
+
+ var exception = Assert.ThrowsAsync(async () => await architecture.InitializeAsync());
+ Assert.That(exception, Is.Not.Null);
+ Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.FailedInitialization));
+
+ await architecture.DestroyAsync();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(destroyOrder, Is.EqualTo(new[] { "model", "utility" }));
+ Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.Destroyed));
+ Assert.That(architecture.PhaseHistory[^3..], Is.EqualTo(new[]
+ {
+ ArchitecturePhase.FailedInitialization,
+ ArchitecturePhase.Destroying,
+ ArchitecturePhase.Destroyed
+ }));
+ });
+ }
+
+ ///
+ /// 验证 Destroyed 阶段会在容器清空前广播给容器内的阶段监听器。
+ /// 该回归测试保护销毁尾声的阶段通知,确保依赖最终阶段信号的服务仍能收到 Destroyed。
+ ///
+ [Test]
+ public async Task DestroyAsync_Should_Notify_Container_Phase_Listeners_About_Destroyed_Before_Clear()
+ {
+ var listener = new TrackingPhaseListener();
+ var architecture = new ListenerTrackingArchitecture(listener);
+
+ await architecture.InitializeAsync();
+ await architecture.DestroyAsync();
+
+ Assert.That(listener.ObservedPhases[^2..], Is.EqualTo(new[]
+ {
+ ArchitecturePhase.Destroying,
+ ArchitecturePhase.Destroyed
+ }));
+ }
+
+ ///
+ /// 验证启用 AllowLateRegistration 时,生命周期层会立即初始化后注册的组件,而不是继续沿用初始化期的拒绝策略。
+ /// 由于公共架构 API 在 Ready 之后会先触发容器限制,此回归测试直接覆盖生命周期协作者的对齐逻辑。
+ ///
+ [Test]
+ public async Task
+ RegisterLifecycleComponent_After_Initialization_Should_Initialize_Immediately_When_LateRegistration_Is_Enabled()
+ {
+ var architecture = new AllowLateRegistrationArchitecture();
+ await architecture.InitializeAsync();
+
+ var lateComponent = new LateRegisteredInitializableComponent();
+
+ architecture.RegisterLateComponentForTesting(lateComponent);
+
+ Assert.That(lateComponent.InitializeCallCount, Is.EqualTo(1));
+
+ await architecture.DestroyAsync();
+ }
+
+ ///
+ /// 记录阶段流转的可配置测试架构。
+ ///
+ 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 FailingInitializationArchitecture : Architecture
+ {
+ private readonly List _destroyOrder;
+
+ ///
+ /// 创建用于验证失败后销毁行为的测试架构。
+ ///
+ /// 记录失败后清理顺序的列表。
+ public FailingInitializationArchitecture(List destroyOrder)
+ {
+ _destroyOrder = destroyOrder;
+ PhaseChanged += phase => PhaseHistory.Add(phase);
+ }
+
+ ///
+ /// 获取架构经历过的阶段列表。
+ ///
+ public List PhaseHistory { get; } = [];
+
+ ///
+ /// 注册可销毁组件后故意抛出异常,模拟初始化失败场景。
+ ///
+ protected override void OnInitialize()
+ {
+ RegisterUtility(new TrackingDestroyableUtility(_destroyOrder));
+ RegisterModel(new TrackingDestroyableModel(_destroyOrder));
+ throw new InvalidOperationException("boom");
+ }
+ }
+
+ ///
+ /// 通过配置器把阶段监听器注册到容器中的测试架构。
+ ///
+ private sealed class ListenerTrackingArchitecture(TrackingPhaseListener listener) : Architecture
+ {
+ ///
+ /// 保持对监听器的引用,以便配置器在初始化前把同一实例注册到容器。
+ ///
+ public override Action? Configurator =>
+ services => services.AddSingleton(listener);
+
+ ///
+ /// 该测试不需要额外组件注册。
+ ///
+ protected override void OnInitialize()
+ {
+ }
+ }
+
+ ///
+ /// 启用 AllowLateRegistration 的测试架构。
+ /// 该架构暴露生命周期协作者供回归测试验证内部注册策略对齐。
+ ///
+ private sealed class AllowLateRegistrationArchitecture : Architecture
+ {
+ ///
+ /// 使用允许后注册的配置创建测试架构。
+ ///
+ public AllowLateRegistrationArchitecture()
+ : base(new ArchitectureConfiguration
+ {
+ ArchitectureProperties = new()
+ {
+ AllowLateRegistration = true,
+ StrictPhaseValidation = true
+ }
+ })
+ {
+ }
+
+ ///
+ /// 该测试不需要初始组件。
+ ///
+ protected override void OnInitialize()
+ {
+ }
+
+ ///
+ /// 通过反射调用内部生命周期协作者的注册逻辑,以便覆盖无法通过公共 API 直接到达的后注册初始化路径。
+ ///
+ /// 要登记到生命周期中的后注册组件。
+ public void RegisterLateComponentForTesting(object component)
+ {
+ var field = typeof(Architecture).GetField(
+ "_lifecycle",
+ BindingFlags.Instance | BindingFlags.NonPublic);
+ var lifecycle = field?.GetValue(this) ??
+ throw new InvalidOperationException("Architecture lifecycle field was not found.");
+ var registerMethod = lifecycle.GetType().GetMethod(nameof(RegisterLateComponentForTesting)) ??
+ lifecycle.GetType().GetMethod("RegisterLifecycleComponent") ??
+ throw new InvalidOperationException(
+ "Architecture lifecycle registration method was not found.");
+
+ registerMethod.Invoke(lifecycle, [component]);
+ }
+ }
+
+ ///
+ /// 用于验证逆序销毁的上下文工具。
+ ///
+ 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 TrackingPhaseListener : IArchitecturePhaseListener
+ {
+ ///
+ /// 获取监听到的阶段列表。
+ ///
+ public List ObservedPhases { get; } = [];
+
+ ///
+ /// 记录收到的阶段通知。
+ ///
+ /// 当前阶段。
+ public void OnArchitecturePhase(ArchitecturePhase phase)
+ {
+ ObservedPhases.Add(phase);
+ }
+ }
+
+ ///
+ /// 记录即时初始化次数的后注册测试组件。
+ ///
+ private sealed class LateRegisteredInitializableComponent : IInitializable
+ {
+ ///
+ /// 获取组件被即时初始化的次数。
+ ///
+ public int InitializeCallCount { get; private set; }
+
+ ///
+ /// 记录一次初始化调用。
+ ///
+ public void Initialize()
+ {
+ InitializeCallCount++;
+ }
+ }
+
+ ///
+ /// 用于验证逆序销毁的模型。
+ ///
+ 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 c3e47436..39b4fd13 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: 模块管理
@@ -37,19 +38,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 +77,6 @@ public abstract class Architecture : IArchitecture
#region Properties
- ///
- /// 获取架构配置对象
- ///
- private IArchitectureConfiguration Configuration { get; }
-
- ///
- /// 获取环境配置对象
- ///
- private IEnvironment Environment { get; }
-
- ///
- /// 获取服务管理器
- ///
- private IArchitectureServices Services { get; }
-
///
/// 当前架构的阶段
///
@@ -129,6 +121,11 @@ public abstract class Architecture : IArchitecture
///
private IArchitectureContext? _context;
+ ///
+ /// 初始化基础设施编排器
+ ///
+ private readonly ArchitectureBootstrapper _bootstrapper;
+
///
/// 生命周期管理器
///
@@ -150,7 +147,8 @@ public abstract class Architecture : IArchitecture
///
/// 注册中介行为管道
- /// 用于配置Mediator框架的行为拦截和处理逻辑
+ /// 用于配置Mediator框架的行为拦截和处理逻辑。
+ /// 可以传入开放泛型行为类型,也可以传入绑定到特定请求的封闭行为类型。
///
/// 行为类型,必须是引用类型
public void RegisterMediatorBehavior() where TBehavior : class
@@ -184,7 +182,7 @@ public abstract class Architecture : IArchitecture
}
///
- /// 注册系统类型,由 DI 容器自动创建实例
+ /// 注册系统类型,由当前服务集合自动创建实例并接入本轮初始化
///
/// 系统类型
/// 可选的实例创建后回调
@@ -205,7 +203,7 @@ public abstract class Architecture : IArchitecture
}
///
- /// 注册模型类型,由 DI 容器自动创建实例
+ /// 注册模型类型,由当前服务集合自动创建实例并接入本轮初始化
///
/// 模型类型
/// 可选的实例创建后回调
@@ -284,32 +282,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 +293,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
diff --git a/GFramework.Core/Architectures/ArchitectureComponentActivator.cs b/GFramework.Core/Architectures/ArchitectureComponentActivator.cs
new file mode 100644
index 00000000..0bf121e5
--- /dev/null
+++ b/GFramework.Core/Architectures/ArchitectureComponentActivator.cs
@@ -0,0 +1,106 @@
+using GFramework.Core.Abstractions.Ioc;
+using GFramework.Core.Abstractions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace GFramework.Core.Architectures;
+
+///
+/// 为架构组件的类型注册路径提供实例创建能力。
+/// 该类型在容器冻结前基于当前服务集合和已注册实例进行激活,
+/// 使 可以在注册阶段就物化 System / Model,
+/// 避免它们在 Ready 之后首次解析时才参与生命周期而导致状态不一致。
+///
+internal sealed class ArchitectureComponentActivator(
+ IIocContainer container,
+ ILogger logger)
+{
+ ///
+ /// 预冻结阶段的单例实例缓存。
+ /// 该缓存跨越整个架构组件激活周期共享,确保多个组件在同一轮初始化中解析到同一个单例描述时不会重复创建实例。
+ ///
+ private readonly Dictionary _singletonCache = [];
+
+ ///
+ /// 根据当前容器状态创建组件实例。
+ /// 激活过程优先复用已经注册到容器中的实例,再按服务描述解析实现类型或工厂方法,
+ /// 以兼容构造函数依赖于框架服务、用户实例服务和先前注册组件的场景。
+ ///
+ /// 要创建的组件类型。
+ /// 创建完成的组件实例。
+ public TComponent CreateInstance() where TComponent : class
+ {
+ var activationProvider = new RegistrationServiceProvider(container, logger, _singletonCache);
+ return ActivatorUtilities.CreateInstance(activationProvider);
+ }
+
+ ///
+ /// 面向组件注册的轻量级服务提供者。
+ /// 该实现只覆盖预冻结阶段需要的解析能力,避免引入完整容器冻结过程。
+ ///
+ private sealed class RegistrationServiceProvider(
+ IIocContainer container,
+ ILogger logger,
+ Dictionary singletonCache) : IServiceProvider
+ {
+ ///
+ /// 共享的单例缓存。
+ /// 该缓存由外层 activator 统一持有,从而把单例复用范围提升到整个组件注册批次,而不是单次实例创建调用。
+ ///
+ private readonly Dictionary _singletonCache = singletonCache;
+
+ ///
+ /// 从当前服务集合中解析指定类型的服务。
+ /// 解析顺序为:已注册实例 → 服务描述实例/工厂/实现类型 → 可直接实例化的具体类型。
+ ///
+ /// 请求解析的服务类型。
+ /// 解析到的服务实例;若无法解析则返回 null。
+ public object? GetService(Type serviceType)
+ {
+ if (serviceType == typeof(IServiceProvider))
+ return this;
+
+ var existingInstance = container.Get(serviceType);
+ if (existingInstance != null)
+ return existingInstance;
+
+ var descriptor =
+ container.GetServicesUnsafe.LastOrDefault(candidate => candidate.ServiceType == serviceType);
+ if (descriptor != null)
+ return ResolveDescriptor(serviceType, descriptor);
+
+ if (!serviceType.IsAbstract && !serviceType.IsInterface)
+ return ActivatorUtilities.CreateInstance(this, serviceType);
+
+ logger.Trace($"Activation provider could not resolve {serviceType.Name}");
+ return null;
+ }
+
+ ///
+ /// 根据服务描述解析实例,并对单例描述进行缓存。
+ /// 这样可以保证同一类型在一次组件注册流程中只创建一次依赖实例。
+ ///
+ /// 请求的服务类型。
+ /// 命中的服务描述。
+ /// 解析到的实例。
+ private object? ResolveDescriptor(Type requestedType, ServiceDescriptor descriptor)
+ {
+ if (descriptor.Lifetime == ServiceLifetime.Singleton &&
+ _singletonCache.TryGetValue(requestedType, out var cached))
+ return cached;
+
+ object? resolved = descriptor switch
+ {
+ { ImplementationInstance: not null } => descriptor.ImplementationInstance,
+ { ImplementationFactory: not null } => descriptor.ImplementationFactory(this),
+ { ImplementationType: not null } => ActivatorUtilities.CreateInstance(this,
+ descriptor.ImplementationType),
+ _ => null
+ };
+
+ if (descriptor.Lifetime == ServiceLifetime.Singleton && resolved != null)
+ _singletonCache[requestedType] = resolved;
+
+ return resolved;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs b/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
index d39d5972..63810c28 100644
--- a/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
+++ b/GFramework.Core/Architectures/ArchitectureComponentRegistry.cs
@@ -20,6 +20,8 @@ internal sealed class ArchitectureComponentRegistry(
ArchitectureLifecycle lifecycle,
ILogger logger)
{
+ private readonly ArchitectureComponentActivator _activator = new(services.Container, logger);
+
#region Validation
///
@@ -63,7 +65,8 @@ internal sealed class ArchitectureComponentRegistry(
}
///
- /// 注册系统类型,由 DI 容器自动创建实例
+ /// 注册系统类型,并在注册阶段由当前服务集合立即创建实例。
+ /// 这样可以确保该系统参与当前架构初始化批次,而不是等到 Ready 之后首次解析时才延迟创建。
///
/// 系统类型
/// 可选的实例创建后回调
@@ -72,21 +75,12 @@ internal sealed class ArchitectureComponentRegistry(
ValidateRegistration("system");
logger.Debug($"Registering system type: {typeof(T).Name}");
- services.Container.RegisterFactory(sp =>
- {
- // 1. DI 创建实例
- var system = ActivatorUtilities.CreateInstance(sp);
-
- // 2. 框架默认处理
- system.SetContext(architecture.Context);
- lifecycle.RegisterLifecycleComponent(system);
-
- // 3. 用户自定义处理(钩子)
- onCreated?.Invoke(system);
-
- logger.Debug($"System created: {typeof(T).Name}");
- return system;
- });
+ // 类型注册路径在注册阶段就物化实例,确保组件能参与当前初始化批次。
+ var system = _activator.CreateInstance();
+ system.SetContext(architecture.Context);
+ lifecycle.RegisterLifecycleComponent(system);
+ onCreated?.Invoke(system);
+ services.Container.RegisterPlurality(system);
logger.Info($"System type registered: {typeof(T).Name}");
}
@@ -118,7 +112,8 @@ internal sealed class ArchitectureComponentRegistry(
}
///
- /// 注册模型类型,由 DI 容器自动创建实例
+ /// 注册模型类型,并在注册阶段由当前服务集合立即创建实例。
+ /// 这样可以确保该模型参与当前架构初始化批次,而不是等到 Ready 之后首次解析时才延迟创建。
///
/// 模型类型
/// 可选的实例创建后回调
@@ -127,18 +122,11 @@ internal sealed class ArchitectureComponentRegistry(
ValidateRegistration("model");
logger.Debug($"Registering model type: {typeof(T).Name}");
- services.Container.RegisterFactory(sp =>
- {
- var model = ActivatorUtilities.CreateInstance(sp);
- model.SetContext(architecture.Context);
- lifecycle.RegisterLifecycleComponent(model);
-
- // 用户自定义钩子
- onCreated?.Invoke(model);
-
- logger.Debug($"Model created: {typeof(T).Name}");
- return model;
- });
+ var model = _activator.CreateInstance();
+ model.SetContext(architecture.Context);
+ lifecycle.RegisterLifecycleComponent(model);
+ onCreated?.Invoke(model);
+ services.Container.RegisterPlurality(model);
logger.Info($"Model type registered: {typeof(T).Name}");
}
@@ -155,6 +143,7 @@ internal sealed class ArchitectureComponentRegistry(
/// 注册成功的工具实例
public TUtility RegisterUtility(TUtility utility) where TUtility : IUtility
{
+ ValidateRegistration("utility");
logger.Debug($"Registering utility: {typeof(TUtility).Name}");
// 处理上下文工具类型的设置和生命周期管理
@@ -177,6 +166,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..c2c7f553
--- /dev/null
+++ b/GFramework.Core/Architectures/ArchitectureDisposer.cs
@@ -0,0 +1,112 @@
+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