// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using System.Diagnostics.CodeAnalysis;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Rule;
using GFramework.Core.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;
using IAsyncCommand = GFramework.Core.Abstractions.Command.IAsyncCommand;
namespace GFramework.Core.Command;
///
/// 表示一个命令执行器,用于执行命令操作。
/// 该类实现了 ICommandExecutor 接口,提供命令执行的核心功能。
///
public sealed class CommandExecutor(ICqrsRuntime? runtime = null) : ICommandExecutor
{
private readonly ICqrsRuntime? _runtime = runtime;
///
/// 获取当前执行器是否已接入统一 CQRS runtime。
///
///
/// 当调用方只是直接 new 一个执行器做纯单元测试时,这里允许为空,并回退到 legacy 直接执行路径;
/// 当执行器由架构容器提供给 使用时,应始终传入 runtime,
/// 以便旧入口也复用统一 pipeline 与 handler 调度链路。
///
public bool UsesCqrsRuntime => _runtime is not null;
///
/// 发送并执行无返回值的命令
///
/// 要执行的命令对象,不能为空
/// 当command参数为null时抛出
public void Send(ICommand command)
{
ArgumentNullException.ThrowIfNull(command);
if (TryExecuteThroughCqrsRuntime(command, static currentCommand => new LegacyCommandDispatchRequest(currentCommand)))
{
return;
}
command.Execute();
}
///
/// 发送并执行有返回值的命令
///
/// 命令执行结果的类型
/// 要执行的命令对象,不能为空
/// 命令执行的结果
/// 当command参数为null时抛出
public TResult Send(ICommand command)
{
ArgumentNullException.ThrowIfNull(command);
if (TryExecuteThroughCqrsRuntime(
command,
static currentCommand => new LegacyCommandResultDispatchRequest(
currentCommand,
() => currentCommand.Execute()),
out TResult? result))
{
return result!;
}
return command.Execute();
}
///
/// 发送并异步执行无返回值的命令
///
/// 要执行的命令对象,不能为空
/// 当command参数为null时抛出
public Task SendAsync(IAsyncCommand command)
{
ArgumentNullException.ThrowIfNull(command);
if (TryResolveDispatchContext(command, out var context))
{
return _runtime.SendAsync(context, new LegacyAsyncCommandDispatchRequest(command)).AsTask();
}
return command.ExecuteAsync();
}
///
/// 发送并异步执行有返回值的命令
///
/// 命令执行结果的类型
/// 要执行的命令对象,不能为空
/// 命令执行的结果
/// 当command参数为null时抛出
public Task SendAsync(IAsyncCommand command)
{
ArgumentNullException.ThrowIfNull(command);
if (TryResolveDispatchContext(command, out var context))
{
return BridgeAsyncCommandWithResultAsync(_runtime, context, command);
}
return command.ExecuteAsync();
}
///
/// 尝试通过统一 CQRS runtime 执行当前 legacy 请求。
///
/// legacy 目标对象类型。
/// bridge request 类型。
/// 即将执行的 legacy 目标对象。
/// 用于创建 bridge request 的工厂。
/// 若成功切入 CQRS runtime 则返回 ;否则返回 。
private bool TryExecuteThroughCqrsRuntime(
TTarget target,
Func requestFactory)
where TTarget : class
where TRequest : IRequest
{
if (!TryResolveDispatchContext(target, out var context))
{
return false;
}
_runtime.SendAsync(context, requestFactory(target)).AsTask().GetAwaiter().GetResult();
return true;
}
///
/// 尝试通过统一 CQRS runtime 执行当前 legacy 请求,并返回装箱结果。
///
/// legacy 目标对象类型。
/// 预期结果类型。
/// bridge request 类型。
/// 即将执行的 legacy 目标对象。
/// 用于创建 bridge request 的工厂。
/// 若命中 bridge,则返回执行结果;否则返回默认值。
/// 若成功切入 CQRS runtime 则返回 ;否则返回 。
private bool TryExecuteThroughCqrsRuntime(
TTarget target,
Func requestFactory,
out TResult? result)
where TTarget : class
where TRequest : IRequest