MediatR:轻松实现命令查询职责分离模式(CQRS)

核心对象

  • IMediator
  • IRequestIRequest<T>
  • IResuestHandler<in TRequest,TResponse>

代码展示

创建名字为MediatorDemo控制台应用,通过nuget引入以下三个包:

MediatR
MediatR.Extensions.Microsoft.DependencyInjection
Microsoft.Extensions.DependencyInjection

创建命令和处理者存放路径

在根目录创建以下两个文件夹:

Commands
CommandHandlers

创建命令

Commands文件夹中创建MyCommand.cs,内容如下

using MediatR;
namespace MediatorDemo.Commands
{
    public class MyDemoCommand:IRequest<string>
    {
        public string Data { get; }
        public MyDemoCommand(string data)
        {
            Data = data;
        }
    }
}

创建命令处理者

CommandHandlers文件夹中创建MyDemoCommandHandler.cs,内容如下:

using System.Threading;
using System.Threading.Tasks;
using MediatorDemo.Commands;
using MediatR;
namespace MediatorDemo.CommandHandlers
{
    public class MyDemoCommandHandler:IRequestHandler<MyDemoCommand,string>
    {
        public async Task<string> Handle(MyDemoCommand request, CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            return $"Hello from MyDemoCommandHandler.Handler -> command data = {request.Data}";
        }
    }
}

发送命令

修改Program.cs,具体内容如下:

using System;
using System.Threading.Tasks;
using MediatorDemo.CommandHandlers;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
namespace MediatorDemo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var service = new ServiceCollection();
            service.AddMediatR(typeof(Program).Assembly);
            var serviceProvider = service.BuildServiceProvider();
            var mediator = serviceProvider.GetService<IMediator>();
            var rsp = await mediator.Send(new MyDemoCommand("This is my demo command"));
            Console.WriteLine(rsp);
        }
    }
}

解释代码:

  • 通过 var service = new ServiceCollection();创建服务容器
  • service.AddMediatR(typeof(Program).Assembly);是想服务容器注册MediatR组件,同时指定MediatR扫描当前Program所在的程序集,获得当前程序集里的所有CommandHandler(通过接口约束)
  • var mediator = serviceProvider.GetService<IMediator>();从服务容器中获取mediator对象
  • var rsp = await mediator.Send(new MyDemoCommand("This is my demo command"));发送一条MyDemoCommand命令

运行代码

运行代码之后可以看到控制台打印以下信息:

Hello from MyDemoCommandHandler.Handler -> command data = This is my demo command

可以看到Program并没有直接去引用MyDemoCommandHandler这个类,只是向MediatR发送了一条指定的命令,MediatR框架会自动去查找该命令对应的Handler,调用Handler里的Handle方法

注意:所谓一对一就是当你有对一个命令有多个Handler的时候,MediatR只会找到最后注册的那个来执行

一对多

核心对象

  • IMediator
  • INotification
  • INotificationHandler<in TNotification>

代码实现

创建事件和事件处理者存放路径

在根目录创建以下两个文件夹:

Events
EventHandlers

创建事件

Events文件夹中创建MyDemoEvent.cs,内容如下:

using MediatR;
namespace MediatorDemo.Events
{
    public class MyDemoEvent:INotification
    {
        public string EventName { get; }
        public MyDemoEvent(string eventName)
        {
            EventName = eventName;
        }
    }
}

创建事件处理者

EventHandlers文件夹中创建MyDemoEventHandler.cs,内容如下:

using System;
using System.Threading;
using System.Threading.Tasks;
using MediatorDemo.Events;
using MediatR;
namespace MediatorDemo.EventHandlers
{
    public class MyDemoEventHandler:INotificationHandler<MyDemoEvent>
    {
        public async Task Handle(MyDemoEvent notification, CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            Console.WriteLine($"MyDemoEventHandler.Handle执行:{notification.EventName}");
        }
    }
    public class MyDemoEventHandlerV2 : INotificationHandler<MyDemoEvent>
    {
        public async Task Handle(MyDemoEvent notification, CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            Console.WriteLine($"MyDemoEventHandlerV2.Handle执行:{notification.EventName}");
        }
    }
}

这里是一个cs文件中写了两个Handler

修改Program

在原有的Main方法最后面添加以下代码:

await mediator.Publish(new MyDemoEvent("MyEvent"));

运行代码

运行项目可以看到以下信息:

Hello from MyDemoCommandHandler.Handler -> command data = This is my demo command
MyDemoEventHandler.Handle执行:MyEvent
MyDemoEventHandlerV2.Handle执行:MyEvent

其中后面两行分别为两个事件处理者打印出来的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值