Mediator.Net
一个强大而灵活的 .NET 中介者模式实现,通过解耦请求/响应处理来实现清洁架构。
📋 目录
🚀 特性
- 命令/查询分离:命令、查询和事件的清晰分离
- 管道支持:用于横切关注点的可扩展中间件管道
- 流式支持:使用
IAsyncEnumerable
处理多个响应 - 依赖注入:内置支持流行的 IoC 容器
- 事件发布:从处理器内部发布事件
- 灵活注册:支持显式注册和程序集扫描注册
- 中间件生态系统:丰富的预构建中间件集合
📦 安装
通过 NuGet 安装主包:
Install-Package Mediator.Net
或通过 .NET CLI:
dotnet add package Mediator.Net
🏁 快速开始
基本设置
// 创建和配置中介者
var mediaBuilder = new MediatorBuilder();
var mediator = mediaBuilder.RegisterHandlers(typeof(Program).Assembly).Build();
定义消息和处理器
// 命令(无响应)
public class CreateUserCommand : ICommand
{
public string Name { get; set; }
public string Email { get; set; }
}
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand>
{
public async Task Handle(IReceiveContext<CreateUserCommand> context, CancellationToken cancellationToken)
{
// 处理命令
var user = new User(context.Message.Name, context.Message.Email);
// 保存用户...
// 发布事件
await context.Publish(new UserCreatedEvent { UserId = user.Id });
}
}
// 请求/响应
public class GetUserQuery : IRequest<UserDto>
{
public int UserId { get; set; }
}
public class GetUserQueryHandler : IRequestHandler<GetUserQuery, UserDto>
{
public async Task<UserDto> Handle(IReceiveContext<GetUserQuery> context, CancellationToken cancellationToken)
{
// 处理查询并返回响应
return new UserDto { Id = context.Message.UserId, Name = "张三" };
}
}
// 事件
public class UserCreatedEvent : IEvent
{
public int UserId { get; set; }
}
public class UserCreatedEventHandler : IEventHandler<UserCreatedEvent>
{
public async Task Handle(IReceiveContext<UserCreatedEvent> context, CancellationToken cancellationToken)
{
// 处理事件
Console.WriteLine($"用户 {context.Message.UserId} 已创建!");
}
}
📋 使用示例
发送命令
// 无响应的命令
await mediator.SendAsync(new CreateUserCommand
{
Name = "张三",
Email = "zhangsan@example.com"
});
// 有响应的命令
var result = await mediator.SendAsync<CreateUserCommand, CreateUserResponse>(
new CreateUserCommand { Name = "李四", Email = "lisi@example.com" });
处理请求
// 有响应的请求
var user = await mediator.RequestAsync<GetUserQuery, UserDto>(
new GetUserQuery { UserId = 123 });
发布事件
// 向所有处理器发布事件
await mediator.Publish(new UserCreatedEvent { UserId = 123 });
流式响应
创建返回多个响应的处理器:
public class GetMultipleUsersStreamHandler : IStreamRequestHandler<GetUsersQuery, UserDto>
{
public async IAsyncEnumerable<UserDto> Handle(
IReceiveContext<GetUsersQuery> context,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
for (var i = 0; i < 10; i++)
{
await Task.Delay(100, cancellationToken);
yield return new UserDto { Id = i, Name = $"用户 {i}" };
}
}
}
// 消费流
await foreach (var user in mediator.CreateStream<GetUsersQuery, UserDto>(new GetUsersQuery()))
{
Console.WriteLine($"接收到:{user.Name}");
}
🔧 处理器注册
程序集扫描(推荐)
var mediator = new MediatorBuilder()
.RegisterHandlers(typeof(Program).Assembly)
.Build();
显式注册
var mediator = new MediatorBuilder()
.RegisterHandlers(() => new List<MessageBinding>
{
new MessageBinding(typeof(CreateUserCommand), typeof(CreateUserCommandHandler)),
new MessageBinding(typeof(GetUserQuery), typeof(GetUserQueryHandler)),
new MessageBinding(typeof(UserCreatedEvent), typeof(UserCreatedEventHandler))
})
.Build();
🔄 管道和中间件
Mediator.Net 支持五种不同场景的管道类型:
管道类型
管道 | 描述 | 触发对象 |
---|---|---|
GlobalReceivePipeline | 对所有消息执行 | 命令、请求、事件 |
CommandReceivePipeline | 仅对命令执行 | ICommand |
RequestReceivePipeline | 仅对请求执行 | IRequest |
EventReceivePipeline | 仅对事件执行 | IEvent |
PublishPipeline | 当事件被发布时执行 | IEvent(出站) |
创建自定义中间件
1. 创建中间件扩展
public static class LoggingMiddleware
{
public static void UseLogging<TContext>(
this IPipeConfigurator<TContext> configurator,
ILogger logger = null)
where TContext : IContext<IMessage>
{
logger ??= configurator.DependencyScope?.Resolve<ILogger>();
configurator.AddPipeSpecification(new LoggingMiddlewareSpecification<TContext>(logger));
}
}
2. 创建中间件规范
public class LoggingMiddlewareSpecification<TContext> : IPipeSpecification<TContext>
where TContext : IContext<IMessage>
{
private readonly ILogger _logger;
public LoggingMiddlewareSpecification(ILogger logger)
{
_logger = logger;
}
public bool ShouldExecute(TContext context, CancellationToken cancellationToken) => true;
public Task BeforeExecute(TContext context, CancellationToken cancellationToken)
{
_logger.LogInformation("正在处理消息:{MessageType}", context.Message.GetType().Name);
return Task.CompletedTask;
}
public Task Execute(TContext context, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task AfterExecute(TContext context, CancellationToken cancellationToken)
{
_logger.LogInformation("完成处理:{MessageType}", context.Message.GetType().Name);
return Task.CompletedTask;
}
public void OnException(Exception ex, TContext context)
{
_logger.LogError(ex, "处理消息时出错:{MessageType}", context.Message.GetType().Name);
throw ex;
}
}
配置管道
var mediator = new MediatorBuilder()
.RegisterHandlers(typeof(Program).Assembly)
.ConfigureGlobalReceivePipe(x => x.UseLogging())
.ConfigureCommandReceivePipe(x => x.UseValidation())
.ConfigureRequestPipe(x => x.UseCaching())
.ConfigureEventReceivePipe(x => x.UseEventStore())
.ConfigurePublishPipe(x => x.UseOutboxPattern())
.Build();
🏗️ 依赖注入集成
Microsoft.Extensions.DependencyInjection
Install-Package Mediator.Net.MicrosoftDependencyInjection
services.AddMediator(builder =>
{
builder.RegisterHandlers(typeof(Program).Assembly);
});
Autofac
Install-Package Mediator.Net.Autofac
var builder = new ContainerBuilder();
var mediatorBuilder = new MediatorBuilder()
.RegisterHandlers(typeof(Program).Assembly);
builder.RegisterMediator(mediatorBuilder);
var container = builder.Build();
其他支持的容器
- SimpleInjector:
Mediator.Net.SimpleInjector
- StructureMap:
Mediator.Net.StructureMap
- Ninject:
Mediator.Net.Ninject
🔌 官方中间件包
Serilog 日志
Install-Package Mediator.Net.Middlewares.Serilog
.ConfigureGlobalReceivePipe(x => x.UseSerilog(LogEventLevel.Information))
工作单元
Install-Package Mediator.Net.Middlewares.UnitOfWork
为事务操作提供 CommittableTransaction
支持。
EventStore 集成
Install-Package Mediator.Net.Middlewares.EventStore
自动将事件持久化到 EventStore。
🎯 高级特性
上下文服务
在中间件和处理器之间共享服务:
// 在中间件中
public Task Execute(TContext context, CancellationToken cancellationToken)
{
context.RegisterService(new AuditInfo { Timestamp = DateTime.UtcNow });
return Task.CompletedTask;
}
// 在处理器中
public async Task Handle(IReceiveContext<MyCommand> context, CancellationToken cancellationToken)
{
if (context.TryGetService(out AuditInfo auditInfo))
{
// 使用审计信息
}
}
从处理器发布事件
public async Task Handle(IReceiveContext<CreateOrderCommand> context, CancellationToken cancellationToken)
{
// 处理命令
var order = new Order(context.Message.CustomerId);
// 发布领域事件
await context.Publish(new OrderCreatedEvent
{
OrderId = order.Id,
CustomerId = order.CustomerId
});
}
📚 文档
更详细的文档、示例和高级场景,请访问我们的 Wiki。
🤝 贡献
我们欢迎贡献!请查看我们的贡献指南了解详情。
📄 许可证
本项目采用 MIT 许可证 - 详情请参阅 LICENSE.txt 文件。
🙋♂️ 支持
- 📖 文档
- 💬 Stack Overflow(使用
mediator.net
标签) - 🐛 问题反馈
⭐ 如果您觉得这个项目有用,请给它一个星标!