feat(architecture): 添加架构核心组件和依赖注入容器实现

- 实现 Architecture 基类,提供系统、模型、工具等组件的注册与管理功能
- 添加 ArchitectureComponentRegistry 组件注册管理器,负责管理系统、模型、工具的注册
- 实现 ArchitectureLifecycle 生命周期管理器,管理架构阶段转换和组件初始化
- 添加 ArchitectureModules 模块管理器,负责架构模块安装和中介行为注册
- 实现 MicrosoftDiContainer 依赖注入容器,包装 Microsoft.Extensions.DependencyInjection
- 提供完整的组件生命周期管理,支持同步和异步初始化模式
- 添加架构阶段管理和组件注册验证机制
This commit is contained in:
GeWuYou 2026-04-05 10:52:21 +08:00
parent 16fae83f70
commit 01dc1523a5
11 changed files with 1046 additions and 189 deletions

View File

@ -74,7 +74,9 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia
/// <summary>
/// 注册中介行为管道
/// 用于配置Mediator框架的行为拦截和处理逻辑
/// 用于配置Mediator框架的行为拦截和处理逻辑。
/// 既支持实现 <c>IPipelineBehavior&lt;,&gt;</c> 的开放泛型行为类型,
/// 也支持绑定到单一请求/响应对的封闭行为类型。
/// </summary>
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
void RegisterMediatorBehavior<TBehavior>()

View File

@ -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;
/// <summary>
/// 验证 Architecture 通过 <c>ArchitectureComponentRegistry</c> 暴露出的组件注册行为。
/// 这些测试覆盖实例注册、工厂注册、上下文注入、生命周期初始化和 Ready 后注册约束,
/// 用于保护组件注册器在继续重构后的既有契约。
/// </summary>
[TestFixture]
public class ArchitectureComponentRegistryBehaviorTests
{
/// <summary>
/// 初始化日志工厂和全局上下文状态。
/// </summary>
[SetUp]
public void SetUp()
{
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
GameContext.Clear();
}
/// <summary>
/// 清理测试过程中绑定到全局表的架构上下文。
/// </summary>
[TearDown]
public void TearDown()
{
GameContext.Clear();
}
/// <summary>
/// 验证系统实例注册会注入上下文并参与生命周期初始化。
/// </summary>
[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<TrackingSystem>(), Is.SameAs(system));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证模型实例注册会注入上下文并参与生命周期初始化。
/// </summary>
[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<TrackingModel>(), Is.SameAs(model));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证上下文工具注册会注入上下文并参与生命周期初始化。
/// </summary>
[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<TrackingContextUtility>(), Is.SameAs(utility));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证普通工具的工厂注册会在首次解析时创建单例并执行创建回调。
/// </summary>
[Test]
public async Task RegisterUtility_Type_Should_Create_Singleton_And_Invoke_Callback()
{
FactoryCreatedUtility? callbackInstance = null;
var architecture = new RegistryTestArchitecture(target =>
target.RegisterUtility<FactoryCreatedUtility>(created => callbackInstance = created));
await architecture.InitializeAsync();
var first = architecture.Context.GetUtility<FactoryCreatedUtility>();
var second = architecture.Context.GetUtility<FactoryCreatedUtility>();
Assert.Multiple(() =>
{
Assert.That(callbackInstance, Is.SameAs(first));
Assert.That(second, Is.SameAs(first));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证 Ready 阶段后不允许继续注册 Utility保持与系统和模型一致的约束。
/// </summary>
[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();
}
/// <summary>
/// 用于测试组件注册行为的最小架构实现。
/// </summary>
private sealed class RegistryTestArchitecture(Action<RegistryTestArchitecture> registrationAction) : Architecture
{
/// <summary>
/// 在初始化阶段执行测试注入的注册逻辑。
/// </summary>
protected override void OnInitialize()
{
registrationAction(this);
}
}
/// <summary>
/// 记录初始化与上下文注入情况的测试系统。
/// </summary>
private sealed class TrackingSystem : ISystem
{
private IArchitectureContext _context = null!;
/// <summary>
/// 获取系统初始化调用次数。
/// </summary>
public int InitializeCallCount { get; private set; }
/// <summary>
/// 记录初始化调用。
/// </summary>
public void Initialize()
{
InitializeCallCount++;
}
/// <summary>
/// 该测试系统不关心阶段变更。
/// </summary>
/// <param name="phase">当前架构阶段。</param>
public void OnArchitecturePhase(ArchitecturePhase phase)
{
}
/// <summary>
/// 存储注入的架构上下文。
/// </summary>
/// <param name="context">架构上下文。</param>
public void SetContext(IArchitectureContext context)
{
_context = context;
}
/// <summary>
/// 返回当前持有的架构上下文。
/// </summary>
public IArchitectureContext GetContext()
{
return _context;
}
/// <summary>
/// 该测试系统没有额外销毁逻辑。
/// </summary>
public void Destroy()
{
}
}
/// <summary>
/// 记录初始化与上下文注入情况的测试模型。
/// </summary>
private sealed class TrackingModel : IModel
{
private IArchitectureContext _context = null!;
/// <summary>
/// 获取模型初始化调用次数。
/// </summary>
public int InitializeCallCount { get; private set; }
/// <summary>
/// 记录初始化调用。
/// </summary>
public void Initialize()
{
InitializeCallCount++;
}
/// <summary>
/// 该测试模型不关心阶段变更。
/// </summary>
/// <param name="phase">当前架构阶段。</param>
public void OnArchitecturePhase(ArchitecturePhase phase)
{
}
/// <summary>
/// 存储注入的架构上下文。
/// </summary>
/// <param name="context">架构上下文。</param>
public void SetContext(IArchitectureContext context)
{
_context = context;
}
/// <summary>
/// 返回当前持有的架构上下文。
/// </summary>
public IArchitectureContext GetContext()
{
return _context;
}
}
/// <summary>
/// 记录初始化与上下文注入情况的测试上下文工具。
/// </summary>
private sealed class TrackingContextUtility : IContextUtility
{
private IArchitectureContext _context = null!;
/// <summary>
/// 获取工具初始化调用次数。
/// </summary>
public int InitializeCallCount { get; private set; }
/// <summary>
/// 记录初始化调用。
/// </summary>
public void Initialize()
{
InitializeCallCount++;
}
/// <summary>
/// 存储注入的架构上下文。
/// </summary>
/// <param name="context">架构上下文。</param>
public void SetContext(IArchitectureContext context)
{
_context = context;
}
/// <summary>
/// 返回当前持有的架构上下文。
/// </summary>
public IArchitectureContext GetContext()
{
return _context;
}
/// <summary>
/// 该测试工具没有额外销毁逻辑。
/// </summary>
public void Destroy()
{
}
}
/// <summary>
/// 用于验证普通工厂注册路径的简单工具。
/// </summary>
private sealed class FactoryCreatedUtility : IUtility
{
}
}

View File

@ -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;
/// <summary>
/// 验证 Architecture 生命周期行为的集成测试。
/// 这些测试覆盖阶段流转、失败状态传播和逆序销毁规则,
/// 用于保护拆分后的生命周期管理、阶段协调与销毁协调行为。
/// </summary>
[TestFixture]
public class ArchitectureLifecycleBehaviorTests
{
/// <summary>
/// 为每个测试准备独立的日志工厂和全局上下文状态。
/// </summary>
[SetUp]
public void SetUp()
{
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
GameContext.Clear();
}
/// <summary>
/// 清理测试注册到全局上下文表的架构上下文。
/// </summary>
[TearDown]
public void TearDown()
{
GameContext.Clear();
}
/// <summary>
/// 验证初始化流程会按既定顺序推进所有生命周期阶段。
/// </summary>
[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();
}
/// <summary>
/// 验证用户初始化失败时,等待 Ready 的任务会失败并进入 FailedInitialization 阶段。
/// </summary>
[Test]
public async Task InitializeAsync_When_OnInitialize_Throws_Should_Mark_FailedInitialization()
{
var architecture = new PhaseTrackingArchitecture(() => throw new InvalidOperationException("boom"));
var exception = Assert.ThrowsAsync<InvalidOperationException>(async () => await architecture.InitializeAsync());
Assert.That(exception, Is.Not.Null);
Assert.That(architecture.CurrentPhase, Is.EqualTo(ArchitecturePhase.FailedInitialization));
Assert.ThrowsAsync<InvalidOperationException>(async () => await architecture.WaitUntilReadyAsync());
}
/// <summary>
/// 验证销毁流程会按注册逆序释放组件,并推进 Destroying/Destroyed 阶段。
/// </summary>
[Test]
public async Task DestroyAsync_Should_Destroy_Components_In_Reverse_Registration_Order()
{
var destroyOrder = new List<string>();
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
}));
});
}
/// <summary>
/// 记录阶段流转的可配置测试架构。
/// </summary>
private sealed class PhaseTrackingArchitecture : Architecture
{
private readonly Action? _onInitializeAction;
/// <summary>
/// 创建一个可选地在用户初始化阶段执行自定义逻辑的测试架构。
/// </summary>
/// <param name="onInitializeAction">用户初始化时执行的测试回调。</param>
public PhaseTrackingArchitecture(Action? onInitializeAction = null)
{
_onInitializeAction = onInitializeAction;
PhaseChanged += phase => PhaseHistory.Add(phase);
}
/// <summary>
/// 获取架构经历过的阶段列表。
/// </summary>
public List<ArchitecturePhase> PhaseHistory { get; } = [];
/// <summary>
/// 执行测试注入的初始化逻辑。
/// </summary>
protected override void OnInitialize()
{
_onInitializeAction?.Invoke();
}
}
/// <summary>
/// 在初始化时注册可销毁组件的测试架构。
/// </summary>
private sealed class DestroyOrderArchitecture : Architecture
{
private readonly List<string> _destroyOrder;
/// <summary>
/// 创建用于验证销毁顺序的测试架构。
/// </summary>
/// <param name="destroyOrder">记录组件销毁顺序的列表。</param>
public DestroyOrderArchitecture(List<string> destroyOrder)
{
_destroyOrder = destroyOrder;
PhaseChanged += phase => PhaseHistory.Add(phase);
}
/// <summary>
/// 获取架构经历过的阶段列表。
/// </summary>
public List<ArchitecturePhase> PhaseHistory { get; } = [];
/// <summary>
/// 注册会记录销毁顺序的 Utility、Model 和 System。
/// </summary>
protected override void OnInitialize()
{
RegisterUtility(new TrackingDestroyableUtility(_destroyOrder));
RegisterModel(new TrackingDestroyableModel(_destroyOrder));
RegisterSystem(new TrackingDestroyableSystem(_destroyOrder));
}
}
/// <summary>
/// 用于验证逆序销毁的上下文工具。
/// </summary>
private sealed class TrackingDestroyableUtility(List<string> 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;
}
}
/// <summary>
/// 用于验证逆序销毁的模型。
/// </summary>
private sealed class TrackingDestroyableModel(List<string> 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;
}
}
/// <summary>
/// 用于验证逆序销毁的系统。
/// </summary>
private sealed class TrackingDestroyableSystem(List<string> 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;
}
}
}

View File

@ -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;
/// <summary>
/// 验证 Architecture 通过 <c>ArchitectureModules</c> 暴露出的模块安装与 Mediator 行为注册能力。
/// 这些测试覆盖模块安装回调和中介管道行为接入,确保模块管理器仍然保持可观察行为不变。
/// </summary>
[TestFixture]
public class ArchitectureModulesBehaviorTests
{
/// <summary>
/// 初始化日志工厂和全局上下文状态。
/// </summary>
[SetUp]
public void SetUp()
{
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
GameContext.Clear();
TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount = 0;
}
/// <summary>
/// 清理测试过程中写入的全局上下文状态。
/// </summary>
[TearDown]
public void TearDown()
{
GameContext.Clear();
TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount = 0;
}
/// <summary>
/// 验证安装模块时会把当前架构实例传给模块,并允许模块在安装阶段注册组件。
/// </summary>
[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<InstalledByModuleUtility>(), Is.Not.Null);
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证注册的 Mediator 行为会参与请求管道执行。
/// </summary>
[Test]
public async Task RegisterMediatorBehavior_Should_Apply_Pipeline_Behavior_To_Request()
{
var architecture = new ModuleTestArchitecture(target =>
target.RegisterMediatorBehavior<TrackingPipelineBehavior<ModuleBehaviorRequest, string>>());
await architecture.InitializeAsync();
var response = await architecture.Context.SendRequestAsync(new ModuleBehaviorRequest());
Assert.Multiple(() =>
{
Assert.That(response, Is.EqualTo("handled"));
Assert.That(TrackingPipelineBehavior<ModuleBehaviorRequest, string>.InvocationCount, Is.EqualTo(1));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 用于测试模块行为的最小架构实现。
/// </summary>
private sealed class ModuleTestArchitecture(Action<ModuleTestArchitecture> registrationAction) : Architecture
{
/// <summary>
/// 打开 Mediator 服务注册,以便测试中介行为接入。
/// </summary>
public override Action<IServiceCollection>? Configurator =>
services => services.AddMediator(options => { options.ServiceLifetime = ServiceLifetime.Singleton; });
/// <summary>
/// 在初始化阶段执行测试注入的模块注册逻辑。
/// </summary>
protected override void OnInitialize()
{
registrationAction(this);
}
}
/// <summary>
/// 记录模块安装调用情况的测试模块。
/// </summary>
private sealed class TrackingArchitectureModule : IArchitectureModule
{
/// <summary>
/// 获取模块安装调用次数。
/// </summary>
public int InstallCallCount { get; private set; }
/// <summary>
/// 获取最近一次接收到的架构实例。
/// </summary>
public IArchitecture? InstalledArchitecture { get; private set; }
/// <summary>
/// 记录安装调用,并在安装阶段注册一个工具验证调用链可用。
/// </summary>
/// <param name="architecture">目标架构实例。</param>
public void Install(IArchitecture architecture)
{
InstallCallCount++;
InstalledArchitecture = architecture;
architecture.RegisterUtility(new InstalledByModuleUtility());
}
}
/// <summary>
/// 由测试模块安装时注册的简单工具。
/// </summary>
private sealed class InstalledByModuleUtility : IUtility
{
}
}
/// <summary>
/// 用于验证管道行为注册是否生效的测试请求。
/// </summary>
public sealed class ModuleBehaviorRequest : IRequest<string>
{
}
/// <summary>
/// 处理测试请求的处理器。
/// </summary>
public sealed class ModuleBehaviorRequestHandler : IRequestHandler<ModuleBehaviorRequest, string>
{
/// <summary>
/// 返回固定结果,便于聚焦验证管道行为是否执行。
/// </summary>
/// <param name="request">请求实例。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>固定响应内容。</returns>
public ValueTask<string> Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken)
{
return ValueTask.FromResult("handled");
}
}
/// <summary>
/// 记录请求通过管道次数的测试行为。
/// </summary>
/// <typeparam name="TRequest">请求类型。</typeparam>
/// <typeparam name="TResponse">响应类型。</typeparam>
public sealed class TrackingPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
/// <summary>
/// 获取当前测试进程中该请求类型对应的行为触发次数。
/// </summary>
public static int InvocationCount { get; set; }
/// <summary>
/// 记录一次行为执行,然后继续执行下一个处理器。
/// </summary>
/// <param name="message">当前请求消息。</param>
/// <param name="next">下一个处理委托。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>下游处理器的响应结果。</returns>
public async ValueTask<TResponse> Handle(
TRequest message,
MessageHandlerDelegate<TRequest, TResponse> next,
CancellationToken cancellationToken)
{
InvocationCount++;
return await next(message, cancellationToken);
}
}

View File

@ -16,6 +16,7 @@ namespace GFramework.Core.Architectures;
/// 专注于生命周期管理、初始化流程控制和架构阶段转换。
///
/// 重构说明:此类已重构为协调器模式,将职责委托给专门的管理器:
/// - ArchitectureBootstrapper: 初始化基础设施编排
/// - ArchitectureLifecycle: 生命周期管理
/// - ArchitectureComponentRegistry: 组件注册管理
/// - ArchitectureModules: 模块管理
@ -146,7 +147,8 @@ public abstract class Architecture : IArchitecture
/// <summary>
/// 注册中介行为管道
/// 用于配置Mediator框架的行为拦截和处理逻辑
/// 用于配置Mediator框架的行为拦截和处理逻辑。
/// 可以传入开放泛型行为类型,也可以传入绑定到特定请求的封闭行为类型。
/// </summary>
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
public void RegisterMediatorBehavior<TBehavior>() where TBehavior : class

View File

@ -155,6 +155,7 @@ internal sealed class ArchitectureComponentRegistry(
/// <returns>注册成功的工具实例</returns>
public TUtility RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility
{
ValidateRegistration("utility");
logger.Debug($"Registering utility: {typeof(TUtility).Name}");
// 处理上下文工具类型的设置和生命周期管理
@ -177,6 +178,7 @@ internal sealed class ArchitectureComponentRegistry(
/// <param name="onCreated">可选的实例创建后回调</param>
public void RegisterUtility<T>(Action<T>? onCreated = null) where T : class, IUtility
{
ValidateRegistration("utility");
logger.Debug($"Registering utility type: {typeof(T).Name}");
services.Container.RegisterFactory<T>(sp =>

View File

@ -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;
/// <summary>
/// 统一处理架构内可销毁对象的登记与释放。
/// 该类型封装逆序销毁、异常隔离和服务模块清理规则,
/// 让 <see cref="ArchitectureLifecycle" /> 可以专注于初始化流程本身。
/// </summary>
internal sealed class ArchitectureDisposer(
IArchitectureServices services,
ILogger logger)
{
/// <summary>
/// 保留注册顺序的可销毁对象列表。
/// 销毁时按逆序遍历,以尽量匹配组件间的依赖方向。
/// </summary>
private readonly List<object> _disposables = [];
/// <summary>
/// 用于去重的可销毁对象集合。
/// </summary>
private readonly HashSet<object> _disposableSet = [];
/// <summary>
/// 注册一个需要参与架构销毁流程的对象。
/// 只有实现 <see cref="IDestroyable" /> 或 <see cref="IAsyncDestroyable" /> 的对象会被跟踪。
/// </summary>
/// <param name="component">待检查的组件实例。</param>
public void Register(object component)
{
if (component is not (IDestroyable or IAsyncDestroyable))
return;
if (!_disposableSet.Add(component))
return;
_disposables.Add(component);
logger.Trace($"Registered {component.GetType().Name} for destruction");
}
/// <summary>
/// 执行架构销毁流程。
/// 该方法会根据当前阶段决定是否进入 Destroying/Destroyed 阶段,并负责服务模块与容器清理。
/// </summary>
/// <param name="currentPhase">销毁开始前的架构阶段。</param>
/// <param name="enterPhase">用于推进架构阶段的回调。</param>
public async ValueTask DestroyAsync(ArchitecturePhase currentPhase, Action<ArchitecturePhase> enterPhase)
{
if (currentPhase >= ArchitecturePhase.Destroying)
{
logger.Warn("Architecture destroy called but already in destroying/destroyed state");
return;
}
if (currentPhase == ArchitecturePhase.None)
{
logger.Debug("Architecture destroy called but never initialized, cleaning up registered components");
await CleanupComponentsAsync();
return;
}
logger.Info("Starting architecture destruction");
enterPhase(ArchitecturePhase.Destroying);
await CleanupComponentsAsync();
await services.ModuleManager.DestroyAllAsync();
services.Container.Clear();
enterPhase(ArchitecturePhase.Destroyed);
logger.Info("Architecture destruction completed");
}
/// <summary>
/// 逆序销毁当前已注册的所有可销毁组件。
/// 单个组件失败不会中断后续清理,避免在销毁阶段留下半清理状态。
/// </summary>
private async ValueTask CleanupComponentsAsync()
{
logger.Info($"Destroying {_disposables.Count} disposable components");
for (var i = _disposables.Count - 1; i >= 0; i--)
{
var component = _disposables[i];
try
{
logger.Debug($"Destroying component: {component.GetType().Name}");
if (component is IAsyncDestroyable asyncDestroyable)
{
await asyncDestroyable.DestroyAsync();
}
else if (component is IDestroyable destroyable)
{
destroyable.Destroy();
}
}
catch (Exception ex)
{
logger.Error($"Error destroying {component.GetType().Name}", ex);
}
}
_disposables.Clear();
_disposableSet.Clear();
}
}

View File

@ -27,11 +27,7 @@ internal sealed class ArchitectureLifecycle(
/// <returns>注册的钩子实例</returns>
public IArchitectureLifecycleHook RegisterLifecycleHook(IArchitectureLifecycleHook hook)
{
if (CurrentPhase >= ArchitecturePhase.Ready && !configuration.ArchitectureProperties.AllowLateRegistration)
throw new InvalidOperationException(
"Cannot register lifecycle hook after architecture is Ready");
_lifecycleHooks.Add(hook);
return hook;
return _phaseCoordinator.RegisterLifecycleHook(hook);
}
#endregion
@ -44,31 +40,32 @@ internal sealed class ArchitectureLifecycle(
/// <param name="component">要注册的组件</param>
public void RegisterLifecycleComponent(object component)
{
// 处理初始化
if (component is IInitializable initializable)
{
if (!_initialized)
if (_initialized)
throw new InvalidOperationException("Cannot initialize component after Architecture is Ready");
if (_pendingInitializableSet.Add(initializable))
{
// 原子去重HashSet.Add 返回 true 表示添加成功(之前不存在)
if (_pendingInitializableSet.Add(initializable))
{
_pendingInitializableList.Add(initializable);
logger.Trace($"Added {component.GetType().Name} to pending initialization queue");
}
}
else
{
throw new InvalidOperationException(
"Cannot initialize component after Architecture is Ready");
_pendingInitializableList.Add(initializable);
logger.Trace($"Added {component.GetType().Name} to pending initialization queue");
}
}
// 处理销毁(支持 IDestroyable 或 IAsyncDestroyable
if (component is not (IDestroyable or IAsyncDestroyable)) return;
// 原子去重HashSet.Add 返回 true 表示添加成功(之前不存在)
if (!_disposableSet.Add(component)) return;
_disposables.Add(component);
logger.Trace($"Registered {component.GetType().Name} for destruction");
_disposer.Register(component);
}
#endregion
#region Phase Management
/// <summary>
/// 进入指定的架构阶段,并执行相应的生命周期管理操作
/// </summary>
/// <param name="next">要进入的下一个架构阶段</param>
public void EnterPhase(ArchitecturePhase next)
{
_phaseCoordinator.EnterPhase(next);
}
#endregion
@ -88,19 +85,15 @@ internal sealed class ArchitectureLifecycle(
private readonly List<IInitializable> _pendingInitializableList = [];
/// <summary>
/// 可销毁组件的去重集合(支持 IDestroyable 和 IAsyncDestroyable
/// 架构阶段协调器
/// </summary>
private readonly HashSet<object> _disposableSet = [];
private readonly ArchitecturePhaseCoordinator _phaseCoordinator =
new(architecture, configuration, services, logger);
/// <summary>
/// 存储所有需要销毁的组件(统一管理,保持注册逆序销毁)
/// 架构销毁协调器
/// </summary>
private readonly List<object> _disposables = [];
/// <summary>
/// 生命周期感知对象列表
/// </summary>
private readonly List<IArchitectureLifecycleHook> _lifecycleHooks = [];
private readonly ArchitectureDisposer _disposer = new(services, logger);
/// <summary>
/// 标记架构是否已初始化完成
@ -114,7 +107,7 @@ internal sealed class ArchitectureLifecycle(
/// <summary>
/// 当前架构的阶段
/// </summary>
public ArchitecturePhase CurrentPhase { get; private set; }
public ArchitecturePhase CurrentPhase => _phaseCoordinator.CurrentPhase;
/// <summary>
/// 获取一个布尔值,指示当前架构是否处于就绪状态
@ -129,87 +122,10 @@ internal sealed class ArchitectureLifecycle(
/// <summary>
/// 阶段变更事件(用于测试和扩展)
/// </summary>
public event Action<ArchitecturePhase>? PhaseChanged;
#endregion
#region Phase Management
/// <summary>
/// 进入指定的架构阶段,并执行相应的生命周期管理操作
/// </summary>
/// <param name="next">要进入的下一个架构阶段</param>
/// <exception cref="InvalidOperationException">当阶段转换不被允许时抛出异常</exception>
public void EnterPhase(ArchitecturePhase next)
public event Action<ArchitecturePhase>? PhaseChanged
{
// 验证阶段转换
ValidatePhaseTransition(next);
// 执行阶段转换
var previousPhase = CurrentPhase;
CurrentPhase = next;
if (previousPhase != next)
logger.Info($"Architecture phase changed: {previousPhase} -> {next}");
// 通知阶段变更
NotifyPhase(next);
NotifyPhaseAwareObjects(next);
// 触发阶段变更事件(用于测试和扩展)
PhaseChanged?.Invoke(next);
}
/// <summary>
/// 验证阶段转换是否合法
/// </summary>
/// <param name="next">目标阶段</param>
/// <exception cref="InvalidOperationException">当阶段转换不合法时抛出</exception>
private void ValidatePhaseTransition(ArchitecturePhase next)
{
// 不需要严格验证,直接返回
if (!configuration.ArchitectureProperties.StrictPhaseValidation)
return;
// FailedInitialization 可以从任何阶段转换,直接返回
if (next == ArchitecturePhase.FailedInitialization)
return;
// 检查转换是否在允许列表中
if (ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) &&
allowed.Contains(next))
return;
// 转换不合法,抛出异常
var errorMsg = $"Invalid phase transition: {CurrentPhase} -> {next}";
logger.Fatal(errorMsg);
throw new InvalidOperationException(errorMsg);
}
/// <summary>
/// 通知所有架构阶段感知对象阶段变更
/// </summary>
/// <param name="phase">新阶段</param>
private void NotifyPhaseAwareObjects(ArchitecturePhase phase)
{
foreach (var obj in services.Container.GetAll<IArchitecturePhaseListener>())
{
logger.Trace($"Notifying phase-aware object {obj.GetType().Name} of phase change to {phase}");
obj.OnArchitecturePhase(phase);
}
}
/// <summary>
/// 通知所有生命周期钩子当前阶段变更
/// </summary>
/// <param name="phase">当前架构阶段</param>
private void NotifyPhase(ArchitecturePhase phase)
{
foreach (var hook in _lifecycleHooks)
{
hook.OnPhase(phase, architecture);
logger.Trace($"Notifying lifecycle hook {hook.GetType().Name} of phase {phase}");
}
add => _phaseCoordinator.PhaseChanged += value;
remove => _phaseCoordinator.PhaseChanged -= value;
}
#endregion
@ -311,72 +227,7 @@ internal sealed class ArchitectureLifecycle(
/// </summary>
public async ValueTask DestroyAsync()
{
// 检查当前阶段,如果已经处于销毁或已销毁状态则直接返回
if (CurrentPhase >= ArchitecturePhase.Destroying)
{
logger.Warn("Architecture destroy called but already in destroying/destroyed state");
return;
}
// 如果从未初始化None 阶段),只清理已注册的组件,不进行阶段转换
if (CurrentPhase == ArchitecturePhase.None)
{
logger.Debug("Architecture destroy called but never initialized, cleaning up registered components");
await CleanupComponentsAsync();
return;
}
// 进入销毁阶段
logger.Info("Starting architecture destruction");
EnterPhase(ArchitecturePhase.Destroying);
// 清理所有组件
await CleanupComponentsAsync();
// 销毁服务模块
await services.ModuleManager.DestroyAllAsync();
services.Container.Clear();
// 进入已销毁阶段
EnterPhase(ArchitecturePhase.Destroyed);
logger.Info("Architecture destruction completed");
}
/// <summary>
/// 清理所有已注册的可销毁组件
/// </summary>
private async ValueTask CleanupComponentsAsync()
{
// 销毁所有实现了 IAsyncDestroyable 或 IDestroyable 的组件(按注册逆序销毁)
logger.Info($"Destroying {_disposables.Count} disposable components");
for (var i = _disposables.Count - 1; i >= 0; i--)
{
var component = _disposables[i];
try
{
logger.Debug($"Destroying component: {component.GetType().Name}");
// 优先使用异步销毁
if (component is IAsyncDestroyable asyncDestroyable)
{
await asyncDestroyable.DestroyAsync();
}
else if (component is IDestroyable destroyable)
{
destroyable.Destroy();
}
}
catch (Exception ex)
{
logger.Error($"Error destroying {component.GetType().Name}", ex);
// 继续销毁其他组件,不会因为一个组件失败而中断
}
}
_disposables.Clear();
_disposableSet.Clear();
await _disposer.DestroyAsync(CurrentPhase, EnterPhase);
}
/// <summary>

View File

@ -14,7 +14,8 @@ internal sealed class ArchitectureModules(
{
/// <summary>
/// 注册中介行为管道
/// 用于配置Mediator框架的行为拦截和处理逻辑
/// 用于配置Mediator框架的行为拦截和处理逻辑。
/// 支持开放泛型行为类型和针对单一请求的封闭行为类型。
/// </summary>
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
public void RegisterMediatorBehavior<TBehavior>() where TBehavior : class

View File

@ -0,0 +1,116 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Logging;
namespace GFramework.Core.Architectures;
/// <summary>
/// 负责架构阶段流转的验证与通知。
/// 该类型集中管理阶段值、生命周期钩子和阶段监听器,避免 <see cref="ArchitectureLifecycle" />
/// 同时承担阶段广播与组件初始化队列管理两类职责。
/// </summary>
internal sealed class ArchitecturePhaseCoordinator(
IArchitecture architecture,
IArchitectureConfiguration configuration,
IArchitectureServices services,
ILogger logger)
{
private readonly List<IArchitectureLifecycleHook> _lifecycleHooks = [];
/// <summary>
/// 获取当前架构阶段。
/// </summary>
public ArchitecturePhase CurrentPhase { get; private set; }
/// <summary>
/// 在架构阶段变更时触发。
/// 该事件用于测试和扩展场景,保持现有公共行为不变。
/// </summary>
public event Action<ArchitecturePhase>? PhaseChanged;
/// <summary>
/// 注册一个生命周期钩子。
/// 就绪后是否允许追加注册由架构配置控制,以保证阶段回调的一致性。
/// </summary>
/// <param name="hook">要注册的生命周期钩子。</param>
/// <returns>原样返回注册的钩子实例,便于链式调用或测试断言。</returns>
public IArchitectureLifecycleHook RegisterLifecycleHook(IArchitectureLifecycleHook hook)
{
if (CurrentPhase >= ArchitecturePhase.Ready && !configuration.ArchitectureProperties.AllowLateRegistration)
throw new InvalidOperationException("Cannot register lifecycle hook after architecture is Ready");
_lifecycleHooks.Add(hook);
return hook;
}
/// <summary>
/// 进入指定阶段并广播给所有阶段消费者。
/// 顺序保持为“更新阶段值 → 生命周期钩子 → 容器中的阶段监听器 → 外部事件”,
/// 以兼容既有调用约定。
/// </summary>
/// <param name="next">目标阶段。</param>
public void EnterPhase(ArchitecturePhase next)
{
ValidatePhaseTransition(next);
var previousPhase = CurrentPhase;
CurrentPhase = next;
if (previousPhase != next)
logger.Info($"Architecture phase changed: {previousPhase} -> {next}");
NotifyLifecycleHooks(next);
NotifyPhaseListeners(next);
PhaseChanged?.Invoke(next);
}
/// <summary>
/// 根据配置验证阶段迁移是否合法。
/// 在关闭严格校验时直接放行,以兼容对阶段流转有特殊需求的宿主。
/// </summary>
/// <param name="next">目标阶段。</param>
/// <exception cref="InvalidOperationException">当迁移不在允许集合中时抛出。</exception>
private void ValidatePhaseTransition(ArchitecturePhase next)
{
if (!configuration.ArchitectureProperties.StrictPhaseValidation)
return;
if (next == ArchitecturePhase.FailedInitialization)
return;
if (ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) && allowed.Contains(next))
return;
var errorMessage = $"Invalid phase transition: {CurrentPhase} -> {next}";
logger.Fatal(errorMessage);
throw new InvalidOperationException(errorMessage);
}
/// <summary>
/// 通知所有生命周期钩子当前阶段已变更。
/// 生命周期钩子通常承载注册表装配等框架扩展逻辑,因此优先于普通阶段监听器执行。
/// </summary>
/// <param name="phase">当前阶段。</param>
private void NotifyLifecycleHooks(ArchitecturePhase phase)
{
foreach (var hook in _lifecycleHooks)
{
hook.OnPhase(phase, architecture);
logger.Trace($"Notifying lifecycle hook {hook.GetType().Name} of phase {phase}");
}
}
/// <summary>
/// 通知容器中的阶段监听器当前阶段已变更。
/// 这些对象通常是系统、模型或工具本身,依赖容器解析保证通知范围与运行时实例一致。
/// </summary>
/// <param name="phase">当前阶段。</param>
private void NotifyPhaseListeners(ArchitecturePhase phase)
{
foreach (var listener in services.Container.GetAll<IArchitecturePhaseListener>())
{
logger.Trace($"Notifying phase-aware object {listener.GetType().Name} of phase change to {phase}");
listener.OnArchitecturePhase(phase);
}
}
}

View File

@ -311,7 +311,9 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <summary>
/// 注册中介行为管道
/// 用于配置Mediator框架的行为拦截和处理逻辑
/// 用于配置Mediator框架的行为拦截和处理逻辑。
/// 同时支持开放泛型行为类型和已闭合的具体行为类型,
/// 以兼容通用行为和针对单一请求的专用行为两种注册方式。
/// </summary>
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
public void RegisterMediatorBehavior<TBehavior>() where TBehavior : class
@ -321,12 +323,35 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton(
typeof(IPipelineBehavior<,>),
typeof(TBehavior)
);
var behaviorType = typeof(TBehavior);
_logger.Debug($"Mediator behavior registered: {typeof(TBehavior).Name}");
if (behaviorType.IsGenericTypeDefinition)
{
GetServicesUnsafe.AddSingleton(typeof(IPipelineBehavior<,>), behaviorType);
}
else
{
var pipelineInterfaces = behaviorType
.GetInterfaces()
.Where(type => type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(IPipelineBehavior<,>))
.ToList();
if (pipelineInterfaces.Count == 0)
{
var errorMessage = $"{behaviorType.Name} does not implement IPipelineBehavior<,>";
_logger.Error(errorMessage);
throw new InvalidOperationException(errorMessage);
}
// 为每个已闭合的管道接口建立显式映射,支持针对特定请求/响应的专用行为。
foreach (var pipelineInterface in pipelineInterfaces)
{
GetServicesUnsafe.AddSingleton(pipelineInterface, behaviorType);
}
}
_logger.Debug($"Mediator behavior registered: {behaviorType.Name}");
}
finally
{