mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
docs(core): 添加 CQRS 文档并完善相关扩展方法
- 新增 CQRS 核心概念、命令查询处理器使用指南 - 添加管道行为、流式处理和最佳实践说明 - 实现 CQRS 协程扩展方法支持异步命令执行 - 添加 ContextAware 接口的 CQRS 命令查询扩展 - 集成 Microsoft DI 容器依赖注入支持 - 补充架构模块行为测试验证功能完整性 - 扩展 GameContext 测试用例提高代码覆盖率
This commit is contained in:
parent
115fe65e88
commit
088f02d586
@ -2,6 +2,7 @@ using GFramework.Core.Abstractions.Lifecycle;
|
||||
using GFramework.Core.Abstractions.Model;
|
||||
using GFramework.Core.Abstractions.Systems;
|
||||
using GFramework.Core.Abstractions.Utility;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GFramework.Core.Abstractions.Architectures;
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using GFramework.Core.Abstractions.Rule;
|
||||
using GFramework.Core.Abstractions.Systems;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GFramework.Core.Abstractions.Ioc;
|
||||
|
||||
|
||||
@ -77,6 +77,28 @@ public class ArchitectureModulesBehaviorTests
|
||||
await architecture.DestroyAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证兼容别名 <c>RegisterMediatorBehavior</c> 仍会把 CQRS 行为接入请求管道。
|
||||
/// </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>
|
||||
|
||||
@ -394,45 +394,106 @@ public class TestArchitectureContext : IArchitectureContext
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发送统一 CQRS 请求。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型。</typeparam>
|
||||
/// <param name="request">要发送的请求。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>请求响应任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask<TResponse> SendRequestAsync<TResponse>(IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:同步发送统一 CQRS 请求。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型。</typeparam>
|
||||
/// <param name="request">要发送的请求。</param>
|
||||
/// <returns>请求响应。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发送 CQRS 命令并返回响应。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">命令响应类型。</typeparam>
|
||||
/// <param name="command">要发送的命令。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>命令响应任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask<TResponse> SendCommandAsync<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:同步发送 CQRS 命令并返回响应。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">命令响应类型。</typeparam>
|
||||
/// <param name="command">要发送的命令。</param>
|
||||
/// <returns>命令响应。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public TResponse SendCommand<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发送 CQRS 查询并返回结果。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">查询结果类型。</typeparam>
|
||||
/// <param name="query">要发送的查询。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>查询结果任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask<TResponse> SendQueryAsync<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:同步发送 CQRS 查询并返回结果。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">查询结果类型。</typeparam>
|
||||
/// <param name="query">要发送的查询。</param>
|
||||
/// <returns>查询结果。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public TResponse SendQuery<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发布 CQRS 通知。
|
||||
/// </summary>
|
||||
/// <typeparam name="TNotification">通知类型。</typeparam>
|
||||
/// <param name="notification">要发布的通知。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>通知发布任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default) where TNotification : INotification
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:创建 CQRS 流式请求响应序列。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">流式响应元素类型。</typeparam>
|
||||
/// <param name="request">流式请求。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>异步响应流。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(
|
||||
IStreamRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
@ -440,12 +501,28 @@ public class TestArchitectureContext : IArchitectureContext
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发送无返回值 CQRS 命令。
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">命令类型。</typeparam>
|
||||
/// <param name="command">要发送的命令。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>命令发送任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask SendAsync<TCommand>(TCommand command, CancellationToken cancellationToken = default)
|
||||
where TCommand : IRequest<Unit>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试桩:异步发送带返回值的 CQRS 请求。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型。</typeparam>
|
||||
/// <param name="command">要发送的请求。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>请求响应任务。</returns>
|
||||
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
|
||||
public ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> command,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
@ -66,6 +66,32 @@ public class CqrsCoroutineExtensionsTests
|
||||
Assert.That(exception, Is.SameAs(expectedException));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 SendCommandCoroutine 在提供错误回调时也会传递解包后的原始异常,
|
||||
/// 避免回调路径暴露 <see cref="AggregateException" />。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SendCommandCoroutine_Should_Forward_Inner_Exception_To_Error_Handler()
|
||||
{
|
||||
var command = new TestCommand("Test");
|
||||
var contextAware = new TestContextAware();
|
||||
var expectedException = new InvalidOperationException("Command failed.");
|
||||
Exception? capturedException = null;
|
||||
|
||||
contextAware.MockContext
|
||||
.Setup(ctx => ctx.SendAsync(command, It.IsAny<CancellationToken>()))
|
||||
.Returns(new ValueTask(Task.FromException(expectedException)));
|
||||
|
||||
var coroutine = CqrsCoroutineExtensions.SendCommandCoroutine(
|
||||
contextAware,
|
||||
command,
|
||||
exception => capturedException = exception);
|
||||
|
||||
Assert.That(coroutine.MoveNext(), Is.True);
|
||||
Assert.That(coroutine.MoveNext(), Is.False);
|
||||
Assert.That(capturedException, Is.SameAs(expectedException));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的简单命令类
|
||||
/// </summary>
|
||||
|
||||
@ -23,4 +23,6 @@ global using GFramework.Core.Abstractions.StateManagement;
|
||||
global using GFramework.Core.Extensions;
|
||||
global using GFramework.Core.Property;
|
||||
global using GFramework.Core.StateManagement;
|
||||
global using GFramework.Core.Abstractions.Property;
|
||||
global using GFramework.Core.Abstractions.Property;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Moq;
|
||||
|
||||
@ -19,6 +19,13 @@ public static class CqrsCoroutineExtensions
|
||||
/// <param name="command">要发送的命令对象。</param>
|
||||
/// <param name="onError">发生异常时的回调处理函数。</param>
|
||||
/// <returns>协程枚举器,用于协程执行。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="command" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// 当底层命令调度失败时,该扩展会把底层异常解包后传给 <paramref name="onError" />,
|
||||
/// 或在未提供回调时重新抛出同一个异常实例,避免两条失败路径暴露不同的异常类型。
|
||||
/// </remarks>
|
||||
public static IEnumerator<IYieldInstruction> SendCommandCoroutine<TCommand>(
|
||||
this IContextAware contextAware,
|
||||
TCommand command,
|
||||
@ -35,9 +42,10 @@ public static class CqrsCoroutineExtensions
|
||||
if (!task.IsFaulted)
|
||||
yield break;
|
||||
|
||||
var exception = task.Exception!.InnerException ?? task.Exception;
|
||||
if (onError != null)
|
||||
onError.Invoke(task.Exception!);
|
||||
onError.Invoke(exception);
|
||||
else
|
||||
throw task.Exception!.InnerException ?? task.Exception;
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,9 @@ public static class ContextAwareCqrsCommandExtensions
|
||||
/// <param name="contextAware">实现 <see cref="IContextAware" /> 接口的对象。</param>
|
||||
/// <param name="command">要发送的命令对象。</param>
|
||||
/// <returns>命令执行结果。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="command" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static TResponse SendCommand<TResponse>(this IContextAware contextAware, ICommand<TResponse> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
@ -31,6 +34,9 @@ public static class ContextAwareCqrsCommandExtensions
|
||||
/// <param name="command">要发送的命令对象。</param>
|
||||
/// <param name="cancellationToken">取消令牌,用于取消操作。</param>
|
||||
/// <returns>包含命令执行结果的 <see cref="ValueTask{TResult}" />。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="command" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask<TResponse> SendCommandAsync<TResponse>(
|
||||
this IContextAware contextAware,
|
||||
ICommand<TResponse> command,
|
||||
|
||||
@ -17,6 +17,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="request">要发送的请求。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>请求结果。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="request" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask<TResponse> SendRequestAsync<TResponse>(
|
||||
this IContextAware contextAware,
|
||||
IRequest<TResponse> request,
|
||||
@ -35,6 +38,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="contextAware">实现 <see cref="IContextAware" /> 接口的对象。</param>
|
||||
/// <param name="request">要发送的请求。</param>
|
||||
/// <returns>请求结果。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="request" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static TResponse SendRequest<TResponse>(this IContextAware contextAware, IRequest<TResponse> request)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
@ -51,6 +57,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="notification">要发布的通知。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="notification" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask PublishAsync<TNotification>(
|
||||
this IContextAware contextAware,
|
||||
TNotification notification,
|
||||
@ -71,6 +80,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="request">流式请求。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>异步响应流。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="request" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static IAsyncEnumerable<TResponse> CreateStream<TResponse>(
|
||||
this IContextAware contextAware,
|
||||
IStreamRequest<TResponse> request,
|
||||
@ -90,6 +102,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="command">要发送的命令。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="command" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask SendAsync<TCommand>(
|
||||
this IContextAware contextAware,
|
||||
TCommand command,
|
||||
@ -110,6 +125,9 @@ public static class ContextAwareCqrsExtensions
|
||||
/// <param name="command">要发送的命令。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>命令执行结果。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="command" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask<TResponse> SendAsync<TResponse>(
|
||||
this IContextAware contextAware,
|
||||
IRequest<TResponse> command,
|
||||
|
||||
@ -15,6 +15,9 @@ public static class ContextAwareCqrsQueryExtensions
|
||||
/// <param name="contextAware">实现 <see cref="IContextAware" /> 接口的对象。</param>
|
||||
/// <param name="query">要发送的查询对象。</param>
|
||||
/// <returns>查询结果。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="query" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static TResponse SendQuery<TResponse>(this IContextAware contextAware, IQuery<TResponse> query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
@ -31,6 +34,9 @@ public static class ContextAwareCqrsQueryExtensions
|
||||
/// <param name="query">要发送的查询对象。</param>
|
||||
/// <param name="cancellationToken">取消令牌,用于取消操作。</param>
|
||||
/// <returns>包含查询结果的 <see cref="ValueTask{TResult}" />。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="contextAware" /> 或 <paramref name="query" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public static ValueTask<TResponse> SendQueryAsync<TResponse>(
|
||||
this IContextAware contextAware,
|
||||
IQuery<TResponse> query,
|
||||
|
||||
@ -16,4 +16,5 @@ global using System.Collections.Generic;
|
||||
global using System.Linq;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
global using System.Threading.Channels;
|
||||
global using System.Threading.Channels;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
using GFramework.Core.Abstractions.Cqrs.Command;
|
||||
using GFramework.Core.Abstractions.Cqrs.Query;
|
||||
using GFramework.Core.Abstractions.Rule;
|
||||
using GFramework.Core.Coroutine;
|
||||
using GFramework.Core.Coroutine.Extensions;
|
||||
using GFramework.Core.Cqrs.Extensions;
|
||||
|
||||
namespace GFramework.Godot.Coroutine;
|
||||
|
||||
@ -26,7 +29,7 @@ public static class ContextAwareCoroutineExtensions
|
||||
string? tag = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Core.Cqrs.Extensions.ContextAwareCqrsCommandExtensions
|
||||
return ContextAwareCqrsCommandExtensions
|
||||
.SendCommandAsync(contextAware, command, cancellationToken)
|
||||
.AsTask()
|
||||
.ToCoroutineEnumerator()
|
||||
@ -50,7 +53,7 @@ public static class ContextAwareCoroutineExtensions
|
||||
string? tag = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Core.Cqrs.Extensions.ContextAwareCqrsCommandExtensions
|
||||
return ContextAwareCqrsCommandExtensions
|
||||
.SendCommandAsync(contextAware, command, cancellationToken)
|
||||
.AsTask()
|
||||
.ToCoroutineEnumerator()
|
||||
@ -74,7 +77,7 @@ public static class ContextAwareCoroutineExtensions
|
||||
string? tag = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Core.Cqrs.Extensions.ContextAwareCqrsQueryExtensions
|
||||
return ContextAwareCqrsQueryExtensions
|
||||
.SendQueryAsync(contextAware, query, cancellationToken)
|
||||
.AsTask()
|
||||
.ToCoroutineEnumerator()
|
||||
@ -97,7 +100,7 @@ public static class ContextAwareCoroutineExtensions
|
||||
string? tag = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Core.Cqrs.Extensions.ContextAwareCqrsExtensions
|
||||
return ContextAwareCqrsExtensions
|
||||
.PublishAsync(contextAware, notification, cancellationToken)
|
||||
.AsTask()
|
||||
.ToCoroutineEnumerator()
|
||||
|
||||
@ -204,22 +204,24 @@ public async Task<List<ScoreData>> GetHighScores()
|
||||
|
||||
### 注册处理器
|
||||
|
||||
在架构中注册 CQRS 行为并让处理器自动扫描注册:
|
||||
在架构中注册 CQRS 行为;默认会自动扫描当前架构所在程序集和 `GFramework.Core` 程序集中的处理器:
|
||||
|
||||
```csharp
|
||||
public class GameArchitecture : Architecture
|
||||
{
|
||||
protected override void Init()
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
// 注册通用开放泛型行为
|
||||
RegisterCqrsPipelineBehavior<LoggingBehavior<,>>();
|
||||
RegisterCqrsPipelineBehavior<PerformanceBehavior<,>>();
|
||||
|
||||
// 处理器会自动通过依赖注入注册
|
||||
// 默认只自动扫描当前架构程序集和 GFramework.Core 程序集中的处理器
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果处理器位于其他模块或扩展程序集中,需要额外接入对应程序集的处理器注册,而不是依赖默认扫描。
|
||||
|
||||
`RegisterCqrsPipelineBehavior<TBehavior>()` 是推荐入口;旧的 `RegisterMediatorBehavior<TBehavior>()`
|
||||
仅作为兼容名称保留。当前接口支持两种形式:
|
||||
|
||||
@ -338,8 +340,8 @@ public class LoggingBehavior<TMessage, TResponse> : IPipelineBehavior<TMessage,
|
||||
{
|
||||
public async ValueTask<TResponse> Handle(
|
||||
TMessage message,
|
||||
CancellationToken cancellationToken,
|
||||
MessageHandlerDelegate<TMessage, TResponse> next)
|
||||
MessageHandlerDelegate<TMessage, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var messageName = message.GetType().Name;
|
||||
Console.WriteLine($"[开始] {messageName}");
|
||||
@ -358,8 +360,8 @@ public class PerformanceBehavior<TMessage, TResponse> : IPipelineBehavior<TMessa
|
||||
{
|
||||
public async ValueTask<TResponse> Handle(
|
||||
TMessage message,
|
||||
CancellationToken cancellationToken,
|
||||
MessageHandlerDelegate<TMessage, TResponse> next)
|
||||
MessageHandlerDelegate<TMessage, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
@ -390,8 +392,8 @@ public class ValidationBehavior<TMessage, TResponse> : IPipelineBehavior<TMessag
|
||||
{
|
||||
public async ValueTask<TResponse> Handle(
|
||||
TMessage message,
|
||||
CancellationToken cancellationToken,
|
||||
MessageHandlerDelegate<TMessage, TResponse> next)
|
||||
MessageHandlerDelegate<TMessage, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 验证输入
|
||||
if (message is IValidatable validatable)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user