.NET Core开发实战(第34课:MediatR:轻松实现命令查询职责分离模式(CQRS))--学习笔记(上)...

本文主要是介绍.NET Core开发实战(第34课:MediatR:轻松实现命令查询职责分离模式(CQRS))--学习笔记(上)...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

核心对象

IMeditator

IRequese、IRequest

IRequestHandler<in TRequest, TResponse>

源码链接:
https://github.com/witskeeper/geektime/tree/master/samples/MediatorDemo

首先我们安装了 MediatR 的 8.0 的组件包,还安装了依赖注入框架的扩展包,以及依赖注入框架的核心组件包

  • MediatR

  • MediatR.Extensions.Microsoft.DependencyInjection

  • Microsoft.Extensions.DependencyInjection

大家可以观察到 MediatR 的包名和命名空间少了一个 o,猜测是作者故意这样设计的,因为它具体实现里面会有一个接口和类是 Mediator,如果设置同名的话会有一些引用上的问题

var services = new ServiceCollection();services.AddMediatR(typeof(Program).Assembly);

我们在这里构建一个 ServiceCollection,然后通过一行代码将我们当前的程序集注入进去,它就可以扫描我们当前程序集相关的类,下面看一下我们定义的两个类

internal class MyCommand : IRequest<long>
{public string CommandName { get; set; }
}internal class MyCommandHandler : IRequestHandler<MyCommand, long>
{public Task<long> Handle(MyCommand request, CancellationToken cancellationToken){Console.WriteLine($"MyCommandHandler执行命令:{request.CommandName}");return Task.FromResult(10L);}
}

第一个类是 MyCommand,它实现了 IRequest 接口,这个接口就代表中介者要执行的命令

第二个类是 MyCommandHandler,它实现了 IRequestHandler 的接口,这个就是我们对命令的处理器的定义

var serviceProvider = services.BuildServiceProvider();var mediator = serviceProvider.GetService<IMediator>();await mediator.Send(new MyCommand { CommandName = "cmd01" });

我们从容器里面获取一个 IMediator,然后通过 send 方法发送一个 MyCommand 命令,我们构造了一个新的 MyCommand 的实例传给它

启动程序,输出如下:

MyCommandHandler执行命令:cmd01

我们可以看到 MyCommandHandler 的 Handle 方法执行了,它输出了 MyCommandHandler 的执行命令 cmd01

这样子,这个中介者它有什么好处呢?

大家可以看到,通过中介者模式,我们将命令的构造和命令的处理可以分离开,那么命令的处理如何知道要处理哪个命令呢,就是通过我们泛型的约束来定义的,我们这里为 IRequestHandler 填入了 MyCommand 类型,所以我们能明确知道 MyCommandHandler 是用来处理 MyCommand 的

如果说我在程序里面实现了多个 Handler,我们可以试验一下

internal class MyEventHandlerV2 : INotificationHandler<MyEvent>
{public Task Handle(MyEvent notification, CancellationToken cancellationToken){Console.WriteLine($"MyEventHandlerV2执行:{notification.EventName}");return Task.CompletedTask;}
}

启动程序,输出如下:

MyCommandHandlerV2执行命令:cmd01

大家可以看到我们输出的是 V2 执行命令

我们把代码进行一个调整,把这个定义移到后面

internal class MyEventHandler : INotificationHandler<MyEvent>
{public Task Handle(MyEvent notification, CancellationToken cancellationToken){Console.WriteLine($"MyEventHandler执行:{notification.EventName}");return Task.CompletedTask;}
}internal class MyEventHandlerV2 : INotificationHandler<MyEvent>
{public Task Handle(MyEvent notification, CancellationToken cancellationToken){Console.WriteLine($"MyEventHandlerV2执行:{notification.EventName}");return Task.CompletedTask;}
}

启动程序,输出如下:

MyCommandHandler执行命令:cmd01

大家可以看到我们这次输出的并不是 V2,而是之前的那个命令,为什么会这样子呢?是因为实际上 mediator 对于 IRequestHandler 的扫描,它是有顺序的,后面扫描到的会替换前面扫描到的 Handler,它只会识别其中最后注册进去的一个,也就是说我们在处理 RequestHandler 的时候,我们要注意在注册时仅注册需要的那个

我们再来看看我们的应用程序,回到我们之前的工程里

namespace GeekTime.API.Application.Commands
{public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, long>{IOrderRepository _orderRepository;ICapPublisher _capPublisher;public CreateOrderCommandHandler(IOrderRepository orderRepository, ICapPublisher capPublisher){_orderRepository = orderRepository;_capPublisher = capPublisher;}public async Task<long> Handle(CreateOrderCommand request, CancellationToken cancellationToken){var address = new Address("wen san lu", "hangzhou", "310000");var order = new Order("xiaohong1999", "xiaohong", 25, address);_orderRepository.Add(order);await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);return order.Id;}}
}

我们可以看到我们的 CreateOrderCommandHandler 实现的是 IRequestHandler,这也就是解释了为什么之前我们并没有显示的调用 CreateOrderCommandHandler,代码却能够执行到这里的原因

这篇关于.NET Core开发实战(第34课:MediatR:轻松实现命令查询职责分离模式(CQRS))--学习笔记(上)...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/355213

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景