using System.Reflection; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Ioc; using GFramework.Cqrs.Abstractions.Cqrs; namespace GFramework.Cqrs.Tests.Cqrs; /// /// 模拟同时提供 handler 注册与 stream invoker 元数据的 generated registry。 /// internal sealed class GeneratedStreamInvokerProviderRegistry : ICqrsHandlerRegistry, ICqrsStreamInvokerProvider, IEnumeratesCqrsStreamInvokerDescriptors { private static readonly CqrsStreamInvokerDescriptor Descriptor = new( typeof(IStreamRequestHandler), typeof(GeneratedStreamInvokerProviderRegistry).GetMethod( nameof(InvokeGenerated), BindingFlags.NonPublic | BindingFlags.Static)!); private static readonly CqrsStreamInvokerDescriptorEntry DescriptorEntry = new( typeof(GeneratedStreamInvokerRequest), typeof(int), Descriptor); /// /// 将测试流式请求处理器注册到目标服务集合。 /// /// 承载处理器映射的服务集合。 /// 用于记录注册诊断的日志器。 public void Register(IServiceCollection services, ILogger logger) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(logger); services.AddTransient( typeof(IStreamRequestHandler), typeof(GeneratedStreamInvokerRequestHandler)); logger.Debug( $"Registered CQRS handler {typeof(GeneratedStreamInvokerRequestHandler).FullName} as {typeof(IStreamRequestHandler).FullName}."); } /// /// 尝试返回指定 stream request/response 类型对对应的 generated invoker 描述符。 /// /// 流式请求运行时类型。 /// 流式响应元素类型。 /// 命中时返回的描述符。 /// 若类型对匹配当前测试流式请求则返回 public bool TryGetDescriptor( Type requestType, Type responseType, out CqrsStreamInvokerDescriptor? descriptor) { if (requestType == typeof(GeneratedStreamInvokerRequest) && responseType == typeof(int)) { descriptor = Descriptor; return true; } descriptor = null; return false; } /// /// 返回当前 registry 暴露的全部 generated stream invoker 描述符。 /// /// 单条测试 stream invoker 描述符条目。 public IReadOnlyList GetDescriptors() { return [DescriptorEntry]; } /// /// 模拟 generated stream invoker 直接执行后的返回值。 /// /// 当前流式请求处理器实例。 /// 当前测试流式请求。 /// 取消令牌。 /// 带有 generated 语义的异步流,便于断言 dispatcher 走了 provider 路径。 private static object InvokeGenerated(object handler, object request, CancellationToken cancellationToken) { _ = handler as IStreamRequestHandler ?? throw new InvalidOperationException("Generated stream invoker received an incompatible handler instance."); var typedRequest = (GeneratedStreamInvokerRequest)request; return StreamResultsAsync(typedRequest.Start, cancellationToken); } /// /// 构造供测试断言使用的固定异步流结果。 /// private static async IAsyncEnumerable StreamResultsAsync( int start, [EnumeratorCancellation] CancellationToken cancellationToken) { yield return start * 10; await Task.Yield(); cancellationToken.ThrowIfCancellationRequested(); yield return start * 10 + 1; } }