mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
feat(architecture): 添加架构核心组件和依赖注入容器实现
- 实现 Architecture 基类,提供系统、模型、工具等组件的注册与管理功能 - 添加 ArchitectureComponentRegistry 组件注册管理器,负责管理系统、模型、工具的注册 - 实现 ArchitectureLifecycle 生命周期管理器,管理架构阶段转换和组件初始化 - 添加 ArchitectureModules 模块管理器,负责架构模块安装和中介行为注册 - 实现 MicrosoftDiContainer 依赖注入容器,包装 Microsoft.Extensions.DependencyInjection - 提供完整的组件生命周期管理,支持同步和异步初始化模式 - 添加架构阶段管理和组件注册验证机制
This commit is contained in:
parent
16fae83f70
commit
01dc1523a5
@ -74,7 +74,9 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia
|
||||
|
||||
/// <summary>
|
||||
/// 注册中介行为管道
|
||||
/// 用于配置Mediator框架的行为拦截和处理逻辑
|
||||
/// 用于配置Mediator框架的行为拦截和处理逻辑。
|
||||
/// 既支持实现 <c>IPipelineBehavior<,></c> 的开放泛型行为类型,
|
||||
/// 也支持绑定到单一请求/响应对的封闭行为类型。
|
||||
/// </summary>
|
||||
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
|
||||
void RegisterMediatorBehavior<TBehavior>()
|
||||
|
||||
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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 =>
|
||||
|
||||
111
GFramework.Core/Architectures/ArchitectureDisposer.cs
Normal file
111
GFramework.Core/Architectures/ArchitectureDisposer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -14,7 +14,8 @@ internal sealed class ArchitectureModules(
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册中介行为管道
|
||||
/// 用于配置Mediator框架的行为拦截和处理逻辑
|
||||
/// 用于配置Mediator框架的行为拦截和处理逻辑。
|
||||
/// 支持开放泛型行为类型和针对单一请求的封闭行为类型。
|
||||
/// </summary>
|
||||
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
|
||||
public void RegisterMediatorBehavior<TBehavior>() where TBehavior : class
|
||||
|
||||
116
GFramework.Core/Architectures/ArchitecturePhaseCoordinator.cs
Normal file
116
GFramework.Core/Architectures/ArchitecturePhaseCoordinator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user