一.nop事件机制简介

应用场景:客户支付成功后,需要发送短信、邮件告知客户订单支付成功(短信、邮件由不同模块实现)

实现方法: 1.定义支付成功OrderPaidEvent事件。

               2.定义短信,邮箱两个消费者共同监听OrderPaidEvent事件,并实现相关业务。

               3.当客户支付成功后生产者发送OrderPaidEvent事件。

               4.消费者接收到OrderPaidEvent事件后,短信和邮箱消费者分别执行自己的业务。

     nop事件机制使用到“生产者/消费者”模式。生产者只负责发布事件,并不需要关心谁来处理,相反消费者只用来处理事件。那生产者和消费者是如何进行关联的呢?nop实现是非常简单的,通过泛型来定义一个事件类,如果生产者和消费者都使用同一个事件类,那么就关联到一起了称之为订阅。负责实现事件机制的部分称之为缓冲区,缓冲区的作用是通过解耦的方式实现消息机制。生产者和消费者是一对多的关系。下图简单介绍下生产者消费者关系。

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

二.nop事件相关接口

生产者接口:Nop.Services.Events.IEventPublisher

消费者接口:Nop.Services.Events.IConsumer<T>

事件订阅接口:Nop.Services.Events.ISubscriptionService

IEventPublisher接口Publish<T>(T eventMessage)方法用于发布事件(生产者)。

IConsumer<T>接口HandleEvent(T eventMessage)方法用于处理事件(消费者)。

两者之间的关系由T泛型来关联,称之为事件,简单的说T类型相同则两者关联订阅成功。

ISubscriptionService接口GetSubscriptions<T>()方法返回IList<IConsumer<T>>集合,该集合保存了消费者。

接口实现如下图:

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训 EventPublisher

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

  1 using System.Collections.Generic;  2 using Nop.Core.Infrastructure;  3   4 namespace Nop.Services.Events  5 {  6     /// <summary>  7     /// 事件订阅服务  8     /// </summary>  9     public class SubscriptionService : ISubscriptionService 10     { 11         /// <summary> 12         /// 获取事件订阅 13         /// </summary> 14         /// <typeparam name="T">Type</typeparam> 15         /// <returns>Event consumers</returns> 16         public IList<IConsumer<T>> GetSubscriptions<T>() 17         { 18             return EngineContext.Current.ResolveAll<IConsumer<T>>(); 19         } 20     } 21 } 22

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

二.消费者IConsermer<T>注册

应用启动时Nop.Web.Framework.DependencyRegistrar中将所有实现IConsumer<T>接口的类注册到ioc容器中。

通过EngineContext.Current.ResolveAll<IConsumer<T>>(),就可以获取到某个消息(T)的订阅了。

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

  1  //注册事件消费者  2             var consumers = typeFinder.FindClassesOfType(typeof(IConsumer<>)).ToList();  3             foreach (var consumer in consumers)  4             {  5                 builder.RegisterType(consumer)  6                     .As(consumer.FindInterfaces((type, criteria) =>  7                     {  8                         var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition());  9                         return isMatch; 10                     }, typeof(IConsumer<>))) 11                     .InstancePerLifetimeScope(); 12             }

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

三.创建消费者

结合上边提到的应用场景,我们创建订阅OrderPaidEvent事件来处理短信通知的消费者。

创建OrderPaidSMSEventConsumer类

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

  1 using System;  2 using Nop.Core;  3 using Nop.Core.Domain.Orders;  4 using Nop.Core.Plugins;  5 using Nop.Services.Events;  6 using Nop.Services.Orders;  7   8 namespace Nop.Plugin.SMS  9 { 10     public class OrderPaidSMSEventConsumer : IConsumer<OrderPaidEvent> 11     { 12  13         private readonly IOrderService _orderService; 14  15         public OrderPaidSMSEventConsumer( 16             IOrderService orderService, 17             IStoreContext storeContext) 18         { 19             this._orderService = orderService; 20             this._storeContext = storeContext; 21         } 22  23         /// <summary> 24         /// 事件处理. 25         /// </summary> 26         /// <param name="eventMessage">The event message.</param> 27         public void HandleEvent(OrderPaidEvent  eventMessage) 28         { 29  30             var order = eventMessage.Order;//获取订单 31  32             //发送短息通知代码 33 	    //.................... 34         } 35     } 36 }

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

OrderPaidSMSEventConsumer类继承 IConsumer<OrderPaidEvent>,OrderPaidEvent就是事件类,维护生产者与消费者之间的订阅关系。事件类名称可以自定义,代表了一个事件。

  

接下来我们再创建一个邮件处理的消费者OrderPaidEmailEventConsumer类,同样继承了ICnsumer<OrderPaidEvent>,说明我们订阅的是也是OrderPaidEvent事件。

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

  1 using System;  2 using Nop.Core;  3 using Nop.Core.Domain.Orders;  4 using Nop.Core.Plugins;  5 using Nop.Services.Events;  6 using Nop.Services.Orders;  7   8 namespace Nop.Plugin.Email  9 { 10     public class OrderPaidEmailEventConsumer : IConsumer<OrderPaidEvent> 11     { 12  13         private readonly IOrderService _orderService; 14         private readonly IStoreContext _storeContext; 15  16         public OrderPaidEmailEventConsumer( 17             IOrderService orderService, 18             IStoreContext storeContext) 19         { 20  21             this._orderService = orderService; 22             this._storeContext = storeContext; 23         } 24  25         /// <summary> 26         /// 邮件处理 27         /// </summary> 28         /// <param name="eventMessage">The event message.</param> 29         public void HandleEvent(OrderPaidEvent eventMessage) 30         { 31  32  33             var order = eventMessage.Order; 34  35             //发送邮件通知客户 36 	    //............................ 37         } 38     } 39 }

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

四.生产消息

我们已经创建了两个订阅了OrderPaidEvent事件的消费者,现在我们看看当客户支付完成时我们是如何通知消费者的。

Nop.Services.OrderProcessingService类中

_eventPublisher.Publish(new OrderPaidEvent(order))方法发送了OrderPaidEvent事件。这时候上边订阅OrderPaidEvent事件的消费(短信、邮件)就会处理消息了。

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

五.nop中常用的事件整理

消费者,主要还是处理缓存

Nop.Web.Infrastructure.Cache.ModelCacheEventConsumer:前台模型相关

Nop.Admin.Infrastructure.Cache.ModelCacheEventConsumer:后台模型相关

Nop.Services.Discounts.Cache.DiscountEventConsumer:折扣相关

Nop.Services.Catalog.Cache.PriceCacheEventConsumer:价格相关

Nop.Services.Customers.Cache.CustomerCacheEventConsumer:密码修改

生产者,下图总结了nop 3.9 源码中自带的事件及所在的类,大部分是未实现对应的消费者。

nop只是在相关的地方留下事件位置,方便我们二次开发的时候进行扩展。

大数据培训,云培训,数据挖掘培训,云计算培训,高端软件开发培训,项目经理培训

六.总结

1.生产者需要继承IEventPublisher接口。

2.消费者需要继承IConsumer<T>接口。

3.消费者通过事件类订阅到生产者,订阅实现参见ISubscriptionService接口。

nop事件机制实现很简单,有兴趣的朋友可以用RabbitMQ进行消息的扩展。

文中有错误的理解和不正确的观点,请留言,一起交流共同进步。

本文地址:http://www.cnblogs.com/yaoshangjin/p/7234522.html

本文为大波浪原创、转载请注明出处。

如果您认为这篇文章还不错或者有所收获,可以点击下方的【关注】按钮,因为你的支持是我继续写作,分享的最大动力!

作者:大波浪

来源:http://www.cnblogs.com/yaoshangjin/

声明: 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果您发现博客中出现了错误,或者有更好的建议、想法,请及时与我联系!!如果想找我私下交流,可以私信或者加我QQ。

http://www.cnblogs.com/yaoshangjin/p/7234522.html