标签:line token strong 一个 方式 wait ebe bool 简单
CQRS(Command Query Responsibility Segregation)命令查询职责分离模式
目标:在控制台中使用Mediatr实现一个简单用户注册场景
- 用户发起用户注册
- 注册成功,发送电子邮件给用户(还可以做其他事情)
- 注册失败,日志记录
控制台程序结构目录
主程序Program.cs 中的代码
class Program
{
static async Task Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
services.AddLogging(logBuilder =>
{
logBuilder.AddConsole();
});
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddScoped(typeof(IPipelineBehavior), typeof(MyLoggerBehavior));
var sp = services.BuildServiceProvider();
var mediator = sp.GetRequiredService();
Console.WriteLine("Hello World!");
while (true)
{
var ss = Console.ReadLine();
Console.WriteLine("------------------注册流程开始-------------------------------------");
mediator.Send(new RegisterCommand("Admin", "123", "123@163.com"));
}
}
}
使用Mediatr 需要引用程序集
PM> Install-Package MediatR
Mediatr 的核心接口
- IMeditator
- IRequest 与IRequestHandler接口,这两个接口是成对存在,一对一关系
- INotification与INotificationHandler接口,是一对多关系
第一步:使用IRequest 创建一个用户注册请求
public class RegisterCommand:IRequest
{
public string UserName { get; private set; }
public string Password { get; private set; }
public string Email { get; private set; }
public RegisterCommand(string userName, string password, string email)
{
UserName = userName;
Password = password;
Email = email;
}
}
第二步:使用IRequestHandler接口 创建一个 “注册请求处理处理程序”
public class RegisterCommandHandler : IRequestHandler
{
private readonly ILogger _logger;
private readonly IMediator _mediator;
public RegisterCommandHandler(ILogger logger, IMediator mediator)
{
_logger = logger;
_mediator = mediator;
}
public async Task Handle(RegisterCommand request, CancellationToken cancellationToken)
{
_logger.LogInformation($"注册命令处理开始时间:{DateTime.Now}==模拟延时1秒注册");
await Task.Delay(1000);
if (DateTime.Now.Second % 2 == 0)
{
_logger.LogInformation($"当前时间:{DateTime.Now}=====注册成功==用户名:{request.UserName}");
_mediator.Publish(new RegisterSucEvent(request.Email));
}
else {
_logger.LogInformation($"当前时间:{DateTime.Now}=====注册失败==用户名:{request.UserName}");
_mediator.Publish(new RegisterFailEvent(request.UserName));
}
_logger.LogInformation($"注册命令处理结束时间:{DateTime.Now}");
return true;
}
}
第三步 使用INotification 接口 两个 通知事件,一个是注册成功事件,另一个是注册失败事件,以及对应的事件处理程序,注册成功事件我写了两个处理程序
注册成功事件
public class RegisterSucEvent : INotification
{
public string Email { get; private set; }
public RegisterSucEvent(string email)
{
Email = email;
}
}
注册成功事件处理程序1
public class RegisterSucEventHandler : INotificationHandler
{
private readonly ILogger _logger;
public RegisterSucEventHandler(ILogger logger)
{
_logger = logger;
}
public async Task Handle(RegisterSucEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation($"RegisterSucEventHandler处理开始时间:{DateTime.Now}==模拟延时5秒发送");
await Task.Delay(5000);
_logger.LogInformation($"时间:{DateTime.Now}=====发送电子邮件给{notification.Email}");
_logger.LogInformation($"RegisterSucEventHandler处理结束时间:{DateTime.Now}");
}
}
注册成功事件处理程序2
public class RegisterSucEventHandlerV2 : INotificationHandler
{
private readonly ILogger _logger;
public RegisterSucEventHandlerV2(ILogger logger)
{
_logger = logger;
}
public async Task Handle(RegisterSucEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation($"RegisterSucEventHandlerV2处理开始时间:{DateTime.Now}==模拟延时5秒发送");
await Task.Delay(5000);
_logger.LogInformation($"吼了两嗓子,用时5秒!");
_logger.LogInformation($"RegisterSucEventHandlerV2处理结束时间:{DateTime.Now}");
}
}
注册失败事件
public class RegisterFailEvent:INotification
{
public string UserName { get; private set; }
public RegisterFailEvent(string userName)
{
UserName = userName;
}
}
注册失败事件事件
public class RegisterFailEventHandler : INotificationHandler
{
private readonly ILogger _logger;
public RegisterFailEventHandler(ILogger logger)
{
_logger = logger;
}
public async Task Handle(RegisterFailEvent notification, CancellationToken cancellationToken)
{
_logger.LogError($"RegisterFailEventHandler处理开始时间:{DateTime.Now}");
_logger.LogError($"时间:{DateTime.Now}=====用户名:{notification.UserName}注册失败");
_logger.LogError($"RegisterFailEventHandler处理结束时间:{DateTime.Now}");
}
}
Mediatr 还有一个管道接口IPipelineBehavior,类似于Aop 编程,可以在IRequest 命令执行前或者执行后加入一些代码逻辑
本程序页实现了一个简单的日志记录行为
public class MyLoggerBehavior:IPipelineBehavior
{
private readonly ILogger> _logger;
public MyLoggerBehavior(ILogger> logger)
{
_logger = logger;
}
public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next)
{
_logger.LogInformation($"命令执行前=={DateTime.Now}");
var result= await next();
_logger.LogInformation($"命令执行后=={DateTime.Now}");
return result;
}
}
OK 整理的代码已经撸完,先理一下执行过程:
主程序启动进行用户注册==>注册成功(延时一秒钟)分别执行RegisterSucEventHandler与RegisterSucEventHandlerV2 处理程序,这个两个程序都要延时5秒钟执行
看下程序执行结果,采用异步的方式
其中RegisterSucEvent有两个处理程序,首先25秒时执行了RegisterSucEventHandler 在30秒执行了RegisterSucEventHandlerV2
注册失败流程
.Net5 中使用Mediatr 中介者模式下的CQRS
标签:line token strong 一个 方式 wait ebe bool 简单
原文地址:https://www.cnblogs.com/acmeblogs/p/14252076.html