Web开发:使用MediatR包实现中介者模式,避免组件之间直接通信

文章目录

一、简介

MediatR 基于中介者模式,是轻量消息中介库,适配 CQRS:拆分 Command(写)/Query(读),通过 Handler 解耦业务逻辑,无需组件直接通信。

二、Program主程序

csharp 复制代码
using WebApplication2.BLL;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

// 注册 MediatR(核心)
builder.Services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});

// 添加 Swagger/OpenAPI 服务(核心配置)
//builder.Services.AddEndpointsApiExplorer(); // 启用端点探索
builder.Services.AddSwaggerGen(options =>
{
    // 可选:配置 Swagger 文档信息(标题、版本、描述)
    options.SwaggerDoc("v1", new Microsoft.OpenApi.OpenApiInfo
    {
        Title = "MediatR WebAPI Demo",
        Version = "v1",
        Description = "集成 MediatR + Swagger 的 WebAPI 示例"
    });
});

var app = builder.Build();

// 配置 Swagger 中间件(开发环境启用,生产环境可关闭)
if (app.Environment.IsDevelopment())
{
    // 启用 Swagger UI
    app.UseSwagger();
    // 配置 Swagger UI 访问路径(默认:/swagger)
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "MediatR Demo API v1");
        // 可选:设置 Swagger UI 为默认首页
        options.RoutePrefix = string.Empty; // 访问根路径直接打开 Swagger
    });
}

app.UseAuthorization();

app.MapControllers();

app.Run();

三、两个模式的定义

请求 - 处理者:一对一,有返回值,用于核心业务逻辑;发布 - 订阅:一对多,无返回值,用于事件联动逻辑。

csharp 复制代码
namespace WebApplication2.BLL
{
    #region 请求-处理者模式入参、出参实体
	//入参:CreateOrderCommand,出参:CreateOrderResponse
    public class CreateOrderCommand : IRequest<CreateOrderResponse>
    {
        [Required(ErrorMessage = "订单编号不能为空")]
        public string OrderNo { get; set; } = string.Empty;

        [Range(0.01, int.MaxValue, ErrorMessage = "订单金额必须大于0")]
        public int Amount { get; set; }
    }

    // 出参:CreateOrderResponse
    public class CreateOrderResponse
    {
        public Guid OrderId { get; set; }
        public string OrderNo { get; set; } = string.Empty;
        public bool Success { get; set; }
    }
    #endregion

    #region 发布-订阅模式事件实体
    // 定义「事件」(发布-订阅,一对多)
    public class OrderCreatedEvent : INotification
    {
        public string OrderNo { get; set; } = string.Empty;
        public int Amount { get; set; }
    }
    #endregion

    #region 处理者
	// IRequestHandler内部写两个实体,一个是入参实体,一个是出参实体
    public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, CreateOrderResponse>
    {
        // Handle 方法:实现具体业务逻辑
        public async Task<CreateOrderResponse> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
        {
            // 模拟业务逻辑:比如写入数据库、调用支付接口等
            Console.WriteLine("【1】开始创建订单:{0},金额:{1}", request.OrderNo, request.Amount);

            // 返回结果
            return new CreateOrderResponse
            {
                OrderId = Guid.NewGuid(),
                OrderNo = request.OrderNo,
                Success = true
            };
        }
    }
    #endregion

    #region 多个订阅者
    // 5. 订阅者1(监听 OrderCreatedEvent)
    public class OrderCreatedHandler1 : INotificationHandler<OrderCreatedEvent>
    {
        public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
        {
            Console.WriteLine("【订阅者1】处理订单后续逻辑:{0},金额:{1}", notification.OrderNo, notification.Amount);
            await Task.CompletedTask; // 模拟异步操作
        }
    }

    // 6. 订阅者2(监听 OrderCreatedEvent)
    public class OrderCreatedHandler2 : INotificationHandler<OrderCreatedEvent>
    {
        public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
        {
            Console.WriteLine("【订阅者2】处理订单后续逻辑:{0},金额:{1}", notification.OrderNo, notification.Amount);
            await Task.CompletedTask; // 模拟异步操作
        }
    }
    #endregion
}

四、高层服务(控制器)

csharp 复制代码
namespace WebApplication2.Controllers
{
    [Route("api/[controller]")]
    [ApiController] // 自动做模型验证
    public class OrdersController : ControllerBase
    {
        // 注入 IMediator(ASP.NET Core 自动管理)
        private readonly IMediator _mediator;

        public OrdersController(IMediator mediator)
        {
            _mediator = mediator;
        }

		//请求-处理者
        [Route(nameof(CreateOrder))]
        [HttpPost]
        public async Task<CreateOrderResponse> CreateOrder(CreateOrderCommand command)
        {
            var response = await _mediator.Send(command);
            return response;
        }

		//发布-订阅
        [Route(nameof(PublishOrder))]
        [HttpPost]
        public async Task<Task> PublishOrder(OrderCreatedEvent command)
        {
             await _mediator.Publish(new OrderCreatedEvent
            {
                OrderNo = command.OrderNo,
                Amount = command.Amount
            });
            return Task.CompletedTask;
        }
    }
}
相关推荐
Highcharts.js2 小时前
数据可视化不仅属于金融、互联网|农业数据可视化设计:Farmable与Highcharts的前端设计
前端·信息可视化·数据可视化·highcharts·农业可视化
JuneXcy2 小时前
node(2)
开发语言·前端·javascript·http·node.js
A923A2 小时前
【Vue3大事件 | 项目笔记】第四天
前端·vue.js·笔记·前端项目
木斯佳2 小时前
前端八股文面经大全:拓竹科技前端一面(2026-03-15)·面经深度解析
前端·css·面试·vue
white-persist2 小时前
【Js逆向 python】Web JS 逆向全体系详细解释
运维·服务器·前端·javascript·网络·python·sql
一拳不是超人2 小时前
龙虾🦞(OpenClaw) 本地部署体验:是真变革还是旧酒装新瓶?
前端·人工智能·程序员
buhuimaren_2 小时前
系统安全及运用
前端·chrome
什么问题2 小时前
记一次 VisionPro +PlayMaker 项目修正
开发语言·前端·javascript
新缸中之脑2 小时前
Chrome 146:终结专用AI浏览器?
前端·人工智能·chrome