首页 > 其他分享 >.net core下使用事件总线

.net core下使用事件总线

时间:2024-08-28 10:48:44浏览次数:9  
标签:core userRepository 总线 eventBus CreateUserCommand 事件 net public

.net core下使用事件总线

          随着微服务的火热,DDD(领域驱动设计模式)思想风起云涌,冲击着整个软件生态系统。其中,事件总线那是必须知道的了,于是我便抱着一个学习DDD的心态搭建了一个博客网站,目前该网站正在建设阶段,后续会不断完善,这里我只是讲一下我里面所用到的事件总线。

      事件总线,我的理解就是发布订阅模式,这里有一篇文章写的比较好,我就是按着这个文章来完成的事件总线:事件总线知多少。我之前按照他的文章结合自己写的,但是今天又看了下自己写的,发现好多都生疏了,所以觉得有必要来回忆下,这里只是我个人的理解,如有不对请指出。

     事件总线就肯定要有事件源,这里我定义一个Command事件源:   
1 2 3 4 5 6 7 /// <summary> /// 领域命令基类(此处文章里我称之为事件源) /// </summary> public  class Command {       }

 然后我根据事件源来定义一个事件源处理的接口和它的实现类:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /// <summary> /// 创建用户领域命令(创建事件源) /// </summary> public class CreateUserCommand: Command {     public CreateUserCommand(User user)     {         User = user;     }     public User User { getprivate set; }   } /// <summary> /// 用户命令处理程序(处理事件源) /// </summary> public class UserCommandHandler : ICommandHandler<CreateUserCommand>, {     private readonly IUserRepository _userRepository;     private readonly IEventBus _eventBus;     public UserCommandHandler(IUserRepository userRepository, IEventBus eventBus)     {         _userRepository = userRepository;         _eventBus = eventBus;     }       public void Handler(CreateUserCommand command)     {         int count = _userRepository.SelectCountByAccount(command.User.Account);         if (count > 0)         {             _eventBus.RaiseEvent(new NotifyValidation("该账号已存在"));             return;         }         _userRepository.Insert(command.User);     } }

     此处我觉得已经完成了关于事件源的功能,那么我们就来思考根据这个事件源来处理发布订阅的关系。

     就那注册用户功能来说,前面已经将注册用户的事件源已经写好了,那么发布订阅怎么处理呢?首先,我们应该清楚一个逻辑,那就是页面生成用户信息,后端获取信息生成UserModel,然后我们根据UserModel转为我们需要的CreateUserCommand,然后我们ICommandHandler根据CreateUserCommand来调用Handler,这是一个简单的调用逻辑。那么IcommandHnadler怎么知道调用哪一个Handler呢?那就是我将事件源和事件源处理类存入集合里面,这样我以后就会根据Command来获取到我的ICommandHandler了,又因为.net core遵循依赖注入原则,所以我需要往容器了注入ICommander和他的实现类,就是UserCommandhandler,这个时候可以说是已经将事件源都注册到了内存里了,以下是我的相关代码:

 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 /// <summary> /// 临时存储类型数组 /// </summary> private static Type[] serviceTypes = Assembly.Load("Blog.Domain").GetTypes();   private static ConcurrentDictionary<Type, IList<Type>> handlerMapping = new ConcurrentDictionary<Type, IList<Type>>();   public static IList<Type> GetOrAddHandlerMapping(this Type eventType) {    return handlerMapping.GetOrAdd(eventType,(Type type)=>new List<Type>()); }   /// <summary> /// 注册事件总线(事件源) /// </summary> /// <typeparam name="TImplementation">ICommandler<CreateUserCommand></typeparam> /// <typeparam name="TService">CreateUserCommand</typeparam> /// <param name="serviceDescriptors"></param> public static void AddEventBus<TImplementation, TService>(this IServiceCollection serviceDescriptors) {     Type handler = typeof(TImplementation);     Type serviceType = serviceTypes.FirstOrDefault(s => handler.IsAssignableFrom(s));//获得接口的实现类     if (serviceType == null)         throw new ArgumentNullException(string.Format("类型{0}未找到实现类", handler.FullName));     serviceDescriptors.AddTransient(handler, serviceType);//.net core自带的IOC容器     GetOrAddHandlerMapping(typeof(TService)).Add(handler);//将事件源和事件源处理程序注册到内存里,可以说生成了一个订阅列表 }

    接下来我们再看发布与订阅,我要先定义一个发布订阅的中间件,

1 2 3 4 5 6 7 8 9 10 11 12 /// <summary>  /// 中间件  /// </summary> public  interface  IEventBus  {      /// <summary>      /// 发布      /// </summary>      /// <typeparam name="TEventData"></typeparam>      /// <param name="eventData"></param>      void Publish<TCommand>(TCommand command) where TCommand : Command;   }

  然后还有它的实现类,处理逻辑就是根据UserCommandHandler去ConcurrentDictionary里找到它的对应的ICommandHandler,然后在从IOC容器找到ICommandHandler的实现类,然后执行里面的方法,如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29   public sealed class EventBus : IEventBus   {       private IServiceProvider _serviceProvider;       public EventBus(IServiceProvider serviceProvider)       {           _serviceProvider = serviceProvider;       }       /// <summary>       /// 发布事件       /// </summary>       /// <typeparam name="TEventData"></typeparam>       /// <param name="eventData"></param>       public void Publish<TCommand>(TCommand command) where TCommand : Command       {           IList<Type> types=typeof(TCommand).GetOrAddHandlerMapping();           if (types == null || types.Count == 0)               throw new ServiceException("事件总线未注册:" typeof(TCommand).Name);           foreach (var type in types)//从订阅列表里寻找           {               object obj = _serviceProvider.GetService(type);               if(type.IsAssignableFrom(obj.GetType()))               {                   ICommandHandler<TCommand> handler = obj as ICommandHandler<TCommand>;                   if (handler != null)                       handler.Handler(command);//               }           }       } }

  这个时候可以说已经完成了发布订阅,程序生成CreateUserCommand,这里我的理解为就是发布,调用Publish方法,这里我觉得就是订阅,然后最后执行Handler完成业务逻辑:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25   public class UserService : IUserService     {         private readonly IUserRepository _userRepository;         private readonly IEventBus _eventBus;         /// <summary>         /// 根据UserModel转实体         /// </summary>         /// <param name="userModel"></param>         /// <returns></returns>         private User TransferModel(UserModel userModel)         {             return user;         }         public UserService(IUserRepository userRepository, IEventBus eventBus)         {             _userRepository = userRepository;             _eventBus = eventBus;         }         public void Insert(UserModel userModel)         {             userModel.Password = EncrypUtil.MD5Encry(userModel.Password);             var command = new CreateUserCommand(TransferModel(userModel));//创建事件源             _eventBus.Publish(command);//发布命令         } }

        还有就是最后的IServiceCollection注入了:

1 2 3 4 5 6 7 8 9 10 11 /// <summary> /// 服务集合 /// </summary> /// <param name="services"></param> public static void AddServices(this IServiceCollection services) {     services.AddTransient<IUserRepository, UserRepository>();     services.AddTransient<IUserService, UserService>();     services.AddEventBus<ICommandHandler<CreateUserCommand>, CreateUserCommand>();<br>            services.AddTransient<IEventBus,EventBus>()     services.DisposeServiceTypes(); }

  以上就是我对事件总线的具体应用,希望有大佬能指出我这菜鸟的不足指出!

        好记性不如烂笔头,所以我把这个玩意用到了我的网站里面,我的个人站点的地址是:www.ttblog.site,源代码的地址是:https://github.com/Hansdas/BlogH.git,个人站点处于建设阶段,很多功能不完善,由于时间原因,所以进度比较慢,但是我也是每天回到家后都会去完善,自己做的饭再难吃也要吃完自己做的网站,不好看也要用心呵护。 

标签:core,userRepository,总线,eventBus,CreateUserCommand,事件,net,public
From: https://www.cnblogs.com/sexintercourse/p/18384154

相关文章

  • 一起来学习.net core程序使用中介者模式:MediatR插件
    一起来学习.netcore程序使用中介者模式:MediatR插件     中介者模式是一种常见的设计模式,旨再降低程序的耦合性,因为传统的三层模式层层之间需要显示的调用,必须上层依赖下层,耦合性很高,为了解耦,将所有的指令单独放在一个位置处理,其他位置均通过这个位置来间接的调用,从......
  • 实用接地气的 .NET 微服务框架
    前言微服务架构已经成为搭建高效、可扩展系统的关键技术之一,然而,现有许多微服务框架往往过于复杂,使得我们普通开发者难以快速上手并体验到微服务带了的便利。为了解决这一问题,于是作者精心打造了一款最接地气的.NET微服务框架,帮助我们轻松构建和管理微服务应用。本框架不仅支......
  • 秃姐学AI系列之:残差网络 ResNet
    目录残差网络——ResNet残差块思想ResNet块细节ResNet架构总结代码实现残差块两种ResNet块的情况 ResNet模型QA由上图发现,只有当较复杂的函数类包含较小的函数类时,才能确保提高它们的性能。对于深度神经网络,如果我们能将新添加的层训练成恒等映射(identityfu......
  • 【计算机组成原理】五、中央处理器:2.数据通路、控制器(单总线结构、专用数据通路、硬布
    3.数据通路文章目录3.数据通路3.1单总线结构3.2专用数据通路4.控制器4.1硬布线控制器4.1.1基本结构4.1.2设计步骤==微操作总结==1)分析每个阶段的微操作序列2)安排微操作时序的原则3)电路设计4.1.3特点4.2微程序控制器==微指令包含关系==4.2.1基本结构4.2.2微指令格式4.......
  • .NET与AI的碰撞:开启智能编程新纪元
    设想一下,你是一名.NET开发者,正为一个复杂的数据分析项目绞尽脑汁。突然,你的IDE仿佛有了生命,不仅能理解你的想法,还能自动生成大部分代码,甚至主动指出潜在的优化空间。这听起来像是科幻电影中的场景,但实际上,这种“魔法”正在成为现实!让我们一同探讨.NET世界正在经历的激动人心的变革......
  • 基于Ubuntu部署企业级kubernetes集群
    1.主机名配置由于本次使用3台主机完成kubernetes集群部署,其中1台为master节点,名称为k8s-master01;其中2台为workoer节点,名称分别为:k8s-worker01及k8s-worker02master节点hostnamectlset-hostnamek8s-master01Worker01节点hostnamectlset-hostnamek8s-worker01Work......
  • 自建 NFS 服务器实现 Kubernetes 持久化存储
    1.简介在Kubernetes集群中,持久化存储是一个非常重要的组件。它允许我们保存需要长期保留的数据,即使Pod被删除或重新调度,这些数据也不会丢失。网络文件系统(NFS)是一种简单、可靠且广泛使用的存储解决方案。本文将详细介绍如何在CentOS7系统上搭建NFS服务器,并......
  • Kubernetes (K8s) 监控方案:Prometheus 实战指南
    1.引言在当今云原生时代,Kubernetes(K8s)已成为容器编排的标准解决方案。然而,随着K8s集群规模和复杂性的增加,有效的监控变得至关重要。本文将详细介绍如何使用Prometheus构建一个全面而强大的K8s监控系统,帮助您实时掌握集群状态,快速定位问题,并优化资源利用。2.监......
  • 驾驭ASP.NET MVC:C# Web开发的精粹
    标题:驾驭ASP.NETMVC:C#Web开发的精粹摘要ASP.NETMVC是微软提供的一个用于构建动态网站的服务器端框架,它遵循模型-视图-控制器(MVC)设计模式,以实现代码的高内聚低耦合。本文将深入探讨如何在C#中使用ASP.NETMVC框架进行Web应用程序开发,包括项目结构、路由、控制器、视图和......
  • FPGA与STM32_FSMC总线通信实验
    在嵌入式系统设计中,FPGA(现场可编程门阵列)与微控制器如STM32的通信是常见的应用场景。STM32通过FSMC(灵活静态存储控制器)接口与FPGA进行数据交换,可以实现高速数据传输和复杂逻辑控制。本文将介绍如何通过FSMC总线实现STM32与FPGA之间的通信。实验目的理解FSMC总线的基本工作......