增加Mediat Pip特性,并用实例来做一个demo

This commit is contained in:
chfei committed 2026-10-22 17:32:58 +08:00
1 parent 292cb8638c
commit c9ac7412ab
19 files changed
+682 -108

No files matched your search

@@ -0,0 +1,26 @@
using FreeSql;
using MediatR;
namespace MAX.Framework.Mediation;
/// <summary>为通过特性选择的命令管理事务;所有读写使用执行上下文中的 ORM。</summary>
public sealed class TransactionBehavior<TRequest, TResponse>(
IFreeSql freeSql, UnitOfWorkExecutionContext context) : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken,
RequestHandlerDelegate<TResponse> next)
{
cancellationToken.ThrowIfCancellationRequested();
if (context.IsActive)
throw new InvalidOperationException("不支持嵌套事务命令,请在同一个命令处理器内完成事务操作");
using var work = freeSql.CreateUnitOfWork();
work.GetOrBeginTransaction();
using var execution = context.Enter(work.Orm);
var response = await next();
cancellationToken.ThrowIfCancellationRequested();
work.Commit();
return response;
// 未提交时,工作单元释放自动回滚;执行上下文同时清理。
}
}
@@ -0,0 +1,27 @@
using System.Threading;
namespace MAX.Framework.Mediation;
/// <summary>沿当前异步调用链传递事务 ORM,隔离并行命令的执行状态。</summary>
public sealed class UnitOfWorkExecutionContext
{
private readonly AsyncLocal<IFreeSql?> _current = new();
public IFreeSql Orm => _current.Value
?? throw new InvalidOperationException("当前操作必须在事务管道内执行");
public bool IsActive => _current.Value != null;
internal IDisposable Enter(IFreeSql orm)
{
if (IsActive)
throw new InvalidOperationException("不支持嵌套事务命令,请在同一个命令处理器内完成事务操作");
_current.Value = orm;
return new ExecutionScope(this);
}
private sealed class ExecutionScope(UnitOfWorkExecutionContext context) : IDisposable
{
public void Dispose() => context._current.Value = null;
}
}
@@ -0,0 +1,18 @@
using MAX.Core.Mediation;
using MediatR;
namespace MAX.Framework.Mediation;
/// <summary>执行请求自身的参数校验,验证通过后才进入后续管道。</summary>
public sealed class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>, IValidatableRequest
{
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken,
RequestHandlerDelegate<TResponse> next)
{
ArgumentNullException.ThrowIfNull(request);
cancellationToken.ThrowIfCancellationRequested();
request.Validate();
return next();
}
}