// Copyright (c) 2025-2026 GeWuYou // SPDX-License-Identifier: Apache-2.0 using System; using System.Collections.Generic; using System.Linq; using GFramework.Core.Abstractions.Bases; using GFramework.Core.Abstractions.Ioc; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Ioc; using Microsoft.Extensions.DependencyInjection; namespace GFramework.Cqrs.Benchmarks.Messaging; /// /// 把冻结后的 benchmark 根容器适配成可重复进入的 request 级解析视图。 /// /// /// `CqrsDispatcher` 会直接依赖 做 handler / pipeline 解析, /// 因此 request lifetime benchmark 需要一个既保留根容器注册元数据,又能在每次 benchmark 调用时把实例解析切换到 /// 显式作用域 provider 的最小适配层。该类型只覆盖 benchmark 当前 request 路径会使用到的解析相关入口; /// 任何注册、清空或冻结修改操作都应继续发生在根容器构建阶段,因此这里统一拒绝可变更 API。 /// internal sealed class ScopedBenchmarkContainer : IIocContainer { private readonly MicrosoftDiContainer _rootContainer; private IServiceScope? _activeScope; private IServiceProvider? _scopedProvider; /// /// 初始化一个绑定到单个 request 作用域的 benchmark 容器适配器。 /// /// 已冻结的 benchmark 根容器。 internal ScopedBenchmarkContainer(MicrosoftDiContainer rootContainer) { _rootContainer = rootContainer ?? throw new ArgumentNullException(nameof(rootContainer)); } /// /// 为当前 benchmark 调用创建并持有一个新的 request 级作用域。 /// /// 离开作用域时负责释放本次 request 级作用域的租约。 /// 当前适配器仍持有上一次尚未释放的作用域。 internal ScopeLease EnterScope() { if (_activeScope is not null) { throw new InvalidOperationException( "Scoped benchmark containers do not support overlapping active scopes."); } _activeScope = _rootContainer.CreateScope(); _scopedProvider = _activeScope.ServiceProvider; return new ScopeLease(this); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 实例类型。 /// 原本要注册到根容器中的单例实例。 /// 当前适配器始终为只读视图。 public void RegisterSingleton(T instance) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 服务契约类型。 /// 服务实现类型。 /// 当前适配器始终为只读视图。 public void RegisterSingleton() where TImpl : class, TService where TService : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 服务契约类型。 /// 服务实现类型。 /// 当前适配器始终为只读视图。 public void RegisterTransient() where TImpl : class, TService where TService : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 服务契约类型。 /// 服务实现类型。 /// 当前适配器始终为只读视图。 public void RegisterScoped() where TImpl : class, TService where TService : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要附加到复数注册集合中的实例。 /// 当前适配器始终为只读视图。 public void RegisterPlurality(object instance) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 复数注册项类型。 /// 当前适配器始终为只读视图。 public void RegisterPlurality() where T : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要注册到容器中的系统实例。 /// 当前适配器始终为只读视图。 public void RegisterSystem(ISystem system) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 实例类型。 /// 原本要注册到容器中的实例。 /// 当前适配器始终为只读视图。 public void Register(T instance) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要绑定的服务类型。 /// 原本要绑定到该类型的实例。 /// 当前适配器始终为只读视图。 public void Register(Type type, object instance) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 工厂要创建的服务类型。 /// 原本要注册的工厂委托。 /// 当前适配器始终为只读视图。 public void RegisterFactory(Func factory) where TService : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要注册的 request pipeline 行为类型。 /// 当前适配器始终为只读视图。 public void RegisterCqrsPipelineBehavior() where TBehavior : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要注册的 stream pipeline 行为类型。 /// 当前适配器始终为只读视图。 public void RegisterCqrsStreamPipelineBehavior() where TBehavior : class { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要扫描 CQRS handler 的程序集。 /// 当前适配器始终为只读视图。 public void RegisterCqrsHandlersFromAssembly(System.Reflection.Assembly assembly) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持在 request 作用域内追加注册。 /// /// 原本要扫描 CQRS handler 的程序集集合。 /// 当前适配器始终为只读视图。 public void RegisterCqrsHandlersFromAssemblies(IEnumerable assemblies) { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持执行额外的服务配置钩子。 /// /// 原本要执行的服务配置委托。 /// 当前适配器始终为只读视图。 public void ExecuteServicesHook(Action? configurator = null) { throw CreateMutationNotSupportedException(); } /// /// 从当前 request 作用域解析单个服务实例。 /// /// 目标服务类型。 /// 解析到的服务实例;若当前作用域未注册则返回 /// 调用方尚未通过 激活作用域。 public T? Get() where T : class { return GetScopedProvider().GetService(); } /// /// 从当前 request 作用域解析单个服务实例。 /// /// 目标服务类型。 /// 解析到的服务实例;若当前作用域未注册则返回 /// /// 调用方尚未通过 激活作用域。 public object? Get(Type type) { ArgumentNullException.ThrowIfNull(type); return GetScopedProvider().GetService(type); } /// /// 从当前 request 作用域解析必需的单个服务实例。 /// /// 目标服务类型。 /// 解析到的服务实例。 /// /// 调用方尚未通过 激活作用域,或当前作用域缺少必需服务。 /// public T GetRequired() where T : class { return GetScopedProvider().GetRequiredService(); } /// /// 从当前 request 作用域解析必需的单个服务实例。 /// /// 目标服务类型。 /// 解析到的服务实例。 /// /// /// 调用方尚未通过 激活作用域,或当前作用域缺少必需服务。 /// public object GetRequired(Type type) { ArgumentNullException.ThrowIfNull(type); return GetScopedProvider().GetRequiredService(type); } /// /// 从当前 request 作用域解析全部服务实例。 /// /// 目标服务类型。 /// 当前作用域中该服务类型的全部实例。 /// 调用方尚未通过 激活作用域。 public IReadOnlyList GetAll() where T : class { return GetScopedProvider().GetServices().ToList(); } /// /// 从当前 request 作用域解析全部服务实例。 /// /// 目标服务类型。 /// 当前作用域中该服务类型的全部实例。 /// /// 调用方尚未通过 激活作用域。 public IReadOnlyList GetAll(Type type) { ArgumentNullException.ThrowIfNull(type); return GetScopedProvider().GetServices(type).Where(static service => service is not null).Cast().ToList(); } /// /// 从当前 request 作用域解析全部服务实例,并按调用方比较器排序。 /// /// 目标服务类型。 /// 用于排序的比较器。 /// 按比较器排序后的服务列表。 /// /// 调用方尚未通过 激活作用域。 public IReadOnlyList GetAllSorted(Comparison comparison) where T : class { ArgumentNullException.ThrowIfNull(comparison); var services = GetAll().ToList(); services.Sort(comparison); return services; } /// /// 从当前 request 作用域解析全部服务实例,并按优先级排序。 /// /// 目标服务类型。 /// 按优先级稳定排序后的服务列表。 /// 调用方尚未通过 激活作用域。 public IReadOnlyList GetAllByPriority() where T : class { return SortByPriority(GetAll()); } /// /// 从当前 request 作用域解析全部服务实例,并按优先级排序。 /// /// 目标服务类型。 /// 按优先级稳定排序后的服务列表。 /// /// 调用方尚未通过 激活作用域。 public IReadOnlyList GetAllByPriority(Type type) { ArgumentNullException.ThrowIfNull(type); return SortByPriority(GetAll(type)); } /// /// 判断根容器是否声明了目标服务键。 /// /// 目标服务类型。 /// 根容器中声明了该服务键时返回 /// /// `CqrsDispatcher` 在热路径上先做注册存在性判断,再决定是否枚举 pipeline;这里沿用根容器冻结后的注册视图, /// 避免把“当前 scope 还未物化实例”误判成“没有注册该行为”。 /// /// public bool HasRegistration(Type type) { ArgumentNullException.ThrowIfNull(type); return _rootContainer.HasRegistration(type); } /// /// 判断根容器是否声明了目标服务键。 /// /// 目标服务类型。 /// 根容器中声明了该服务键时返回 public bool Contains() where T : class { return _rootContainer.Contains(); } /// /// 当前 request 作用域适配器不追踪实例归属。 /// /// 待检查的实例。 /// 若根容器已追踪该实例,则返回根容器的检查结果。 public bool ContainsInstance(object instance) { return _rootContainer.ContainsInstance(instance); } /// /// 当前适配器不支持清空注册。 /// /// 当前适配器始终为只读视图。 public void Clear() { throw CreateMutationNotSupportedException(); } /// /// 当前适配器不支持重新冻结。 /// /// 当前适配器始终为只读视图。 public void Freeze() { throw CreateMutationNotSupportedException(); } /// /// 继续暴露根容器底层服务集合,仅用于接口兼容。 /// /// 根容器当前持有的底层服务集合。 public IServiceCollection GetServicesUnsafe => _rootContainer.GetServicesUnsafe; /// /// 基于当前 request 作用域继续创建嵌套作用域。 /// /// 从当前激活作用域继续派生出的子作用域。 /// 调用方尚未通过 激活作用域。 public IServiceScope CreateScope() { return GetScopedProvider().CreateScope(); } /// /// 将上下文转发给根容器,保持与 request 生命周期无关的上下文缓存行为一致。 /// /// 要绑定到根容器的架构上下文。 public void SetContext(GFramework.Core.Abstractions.Architectures.IArchitectureContext context) { ((IContextAware)_rootContainer).SetContext(context); } /// /// 读取根容器当前持有的架构上下文。 /// /// 根容器当前保存的架构上下文。 public GFramework.Core.Abstractions.Architectures.IArchitectureContext GetContext() { return ((IContextAware)_rootContainer).GetContext(); } /// /// 释放当前 request 适配器时,同时兜底释放任何尚未归还的激活作用域。 /// public void Dispose() { ReleaseActiveScope(); } /// /// 读取当前激活的 request 级作用域服务提供器。 /// /// 当前作用域对应的服务提供器。 /// 调用方尚未通过 激活作用域。 private IServiceProvider GetScopedProvider() { return _scopedProvider ?? throw new InvalidOperationException( "Scoped benchmark containers require an active scope. Call EnterScope() before resolving scoped services."); } /// /// 释放当前激活的 request 级作用域,并清空解析视图。 /// private void ReleaseActiveScope() { _scopedProvider = null; var activeScope = _activeScope; _activeScope = null; activeScope?.Dispose(); } /// /// 生成统一的只读适配器异常,避免 benchmark 误把 request 级容器当成可变组合根。 /// /// 描述当前适配器只读语义的统一异常。 private static InvalidOperationException CreateMutationNotSupportedException() { return new InvalidOperationException( "Scoped benchmark containers are read-only request views. Mutate registrations on the root benchmark host before freezing it."); } /// /// 复用与根容器一致的优先级排序语义。 /// /// 服务实例类型。 /// 待排序服务集合。 /// 按优先级稳定排序后的服务列表。 private static IReadOnlyList SortByPriority(IReadOnlyList services) where T : class { if (services.Count <= 1) { return services; } return services .Select((service, index) => new { Service = service, Index = index }) .OrderBy(static x => { var priority = x.Service is IPrioritized prioritized ? prioritized.Priority : 0; return (priority, x.Index); }) .Select(static x => x.Service) .ToList(); } /// /// 表示一次激活中的 request 级作用域租约。 /// internal readonly struct ScopeLease : IDisposable { private readonly ScopedBenchmarkContainer _owner; /// /// 初始化一个绑定到目标适配器的作用域租约。 /// /// 拥有当前作用域的 benchmark 容器适配器。 internal ScopeLease(ScopedBenchmarkContainer owner) { _owner = owner ?? throw new ArgumentNullException(nameof(owner)); } /// /// 释放当前 request 级作用域。 /// public void Dispose() { _owner.ReleaseActiveScope(); } } }