Nopcommerce 之事件机制

Nop有着完善的事件机制,在框架中也多次用到。比如删除删除电子邮件时删除指定的缓存、更新实体时,更新缓存等。这里用到的是“生产者/消费者”模式,该模式中,定义了对象之间一对多的依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。生产者发布事件,消费者处理事件。

一.相关接口和类:

1.IEventPublisher事件发布接口。

2.EventPublisher实现IEventPublisher的类,主要功能包括发布事件并通知订阅者。

3.IConsumer<T>消费者(事件订阅者)接口。

4.ISubscriptionService订阅者接口,解析所有的订阅者。

5.SubscriptionService的具体实现。

二注册事件:

如果用户想要侦听事件,就需要注册成为消费者。消费者接口IConsumer<T>为一个泛型接口,里面有一个处理事件的方法。IConsumer<T>接口代码如下:

/// <summary>
    /// 消费者
    /// </summary>
    public interface IConsumer<T>
    {
        void HandleEvent(T eventMessage);
    }

在该框架中,实现IConsumer<T>接口的类很多比如Nop.Admin.Infrastructure.Cache.ModelCacheEventConsumer代码如下:

public partial class ModelCacheEventConsumer : IConsumer<EntityUpdated<UrlRecord>>
    {
        public void HandleEvent(EntityUpdated<UrlRecord> eventMessage)
        {
            throw new NotImplementedException();
        }
        #region KEY
        /// <summary>
        /// Key for widget info
        /// </summary>
        /// <remarks>
        /// {0} : current store ID
        /// {1} : widget zone
        /// {2} : current theme name
        /// </remarks>
        public const string WIDGET_MODEL_KEY = "NopFramework.pres.widget-{0}";
        public const string WIDGET_PATTERN_KEY = "NopFramework.pres.widget";
        #endregion
    }

“HandleEvent”为对应的事件处理方法,可以根据需要处理。实现了“IConsumer<T>”接口就注册成为了订阅者,当有任何消息发布时,就能真听到对应的事件。

三.事件订阅

事件订阅主要就是解析哪些用户订阅了事件,这样当事件发生时,才能准确的发送到指定的用户。订阅接口如下:

/// <summary>
    /// 事件订阅服务
    /// </summary>
    public interface ISubscriptionService
    {
        IList<IConsumer<T>> GetSubscriptions<T>();
    }

该接口只有一个获取一个方法--获取所有注册事件的用户。实现该类具体如下:

/// <summary>
    /// 事件订阅服务
    /// </summary>
    public class SubscriptionService : ISubscriptionService
    {
        public IList<IConsumer<T>> GetSubscriptions<T>()
        {
            return EngineContext.Current.ResolveAll<IConsumer<T>>();//
        }
    }

四.事件发布

事件发布接口“IEventPublisher”。该接口只包含一个方法:

 /// <summary>
    /// 事件发布接口
    /// </summary>
    public interface IEventPublisher
    {
        /// <summary>
        /// 事件发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="eventMessage"></param>
        void Publish<T>(T eventMessage);
    }

具体的实现如下:

 public class EventPublisher : IEventPublisher
    {
        private readonly ISubscriptionService _subscriptionService;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="subscriptionService"></param>
        public EventPublisher(ISubscriptionService subscriptionService)
        {
            this._subscriptionService = subscriptionService;
        }
        /// <summary>
        /// 发布事件,通知订阅者
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="x"></param>
        /// <param name="eventMessage"></param>
        public virtual void PublishToConsumer<T>(IConsumer<T> x,T eventMessage)
        {
            try
            {
                x.HandleEvent(eventMessage);
            }
            catch (Exception exc)
            {
                var logger= EngineContext.Current.Resolve<ILogger>();
                try
                {
                    logger.Error(exc.Message, exc);
                }
                catch (Exception)
                {
                }
            }
        }
        /// <summary>
        /// 根据位于其程序集中的某个类型找到一个插件描述符
        /// </summary>
        /// <param name="providerType"></param>
        /// <returns></returns>
        protected virtual PluginDescriptor FindPlugin(Type providerType)
        {
            if (providerType == null)
                throw new ArgumentNullException("providerType");

            if (PluginManager.ReferencedPlugins == null)
                return null;
            foreach (var plugin in PluginManager.ReferencedPlugins)
            {
                if (plugin.ReferencedAssembly == null)
                    continue;

                if (plugin.ReferencedAssembly.FullName == providerType.Assembly.FullName)
                    return plugin;
            }

            return null;
        }
        /// <summary>
        /// 发布事件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="eventMessage"></param>
        public virtual void Publish<T>(T eventMessage)
        {
            var subscriptions = _subscriptionService.GetSubscriptions<T>();//查找所有注册事件的用户
            subscriptions.ToList().ForEach(x=>PublishToConsumer(x,eventMessage));
        }
    }

先看下“Publish<T>(T eventMessage)”方法,该方法是由其他方法比如更新或者删除实体后调用,触发事件。然后调用ISubscriptionService 接口的“GetSubscriptions”方法,查找所有注册该接口的事件,之后逐条遍历订阅者,执行“PublishToConsumer”方法,发布事件,通知订阅者,具体的处理,可在“HandleEvent”实现;

时间: 2024-08-25 00:42:15

Nopcommerce 之事件机制的相关文章

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

Qt事件机制概览

Qt事件机制概览 Qt事件机制概览 消息循环 Qt事件循环 简介 QEventLoop 跨线程的信号和槽与事件循环 模态窗口 Native widget or Alien widget 创建Native widget 创建QApplication的message-only窗口 派发事件的公共基础方法 source code QApplication的创建过程 QWidget native QWidget 的创建过程 普通native widget回调过程 QApplication的message

JavaScript事件机制

<script type="text/javascript" src="http://runjs.cn/gist/2zmltkfa/all"></script> [前端培养-作业01]javascript事件机制 1.javascript事件模型 2.e.target与e.currentTarget是干什么的? 3.preventDefault与stopPropagation是干什么的 4.什么是dispatchEvent? 5.说一说事件代

Android-- Android事件机制之二:onTouch详解

Android事件机制之二:onTouch详解 在其中对OntouchEvent中的总结中,不是很具体.本文将主要对onTouch进行总结. onTouch是Android系统中整个事件机制的基础.Android中的其他事件,如onClick.onLongClick等都是以onTouch为基础的. onTouch包括从手指按下到离开手机屏幕的整个过程,在微观形式上,具体表现为action_down.action_move和action_up等过程. onTouch两种主要定义形式如下: (1)在

聊一聊Android的事件机制

侯 亮 1概述 在Android平台上,主要用到两种通信机制,即Binder机制和事件机制,前者用于跨进程通信,后者用于进程内部通信. 从技术实现上来说,事件机制还是比较简单的.从大的方面讲,不光是Android平台,各种平台的消息机制的原理基本上都是相近的,其中用到的主要概念大概有: 1)消息发送者: 2)消息队列: 3)消息处理循环. 示意图如下: 图中表达的基本意思是,消息发送者通过某种方式,将消息发送到某个消息队列里,同时还有一个消息处理循环,不断从消息队列里摘取消息,并进一步解析处理.

Nginx处理stale事件机制分析

Nginx为提高效率采用描述符缓冲池(连接池)来处理tcp连接,一个连接对应一个读事件和一个写事件,nginx在启动的时候会创建好所用连接和事件,当事件来的时候不用再创建,然而连接池的使用却存在stale事件的问题,以下将详细分析Nginx是如何处理stale事件的,该问题涉及到epoll.Nginx连接与事件的相关知识. 1      Epoll的实现原理 epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait.Linux-2.6.19又引入了可以屏蔽

Node.js入门:事件机制

Evented I/O for V8 JavaScript 基于V8引擎实现的事件驱动IO. 事件机制的实现 Node.js中大部分的模块,都继承自Event模块(http://nodejs.org/docs/latest/api/events.html ).Event模块(events.EventEmitter)是一个简单的事件监听器模式的实现.具有addListener/on,once,removeListener,removeAllListeners,emit等基本的事件监听模式的方法实现

舌尖上的安卓(android触控事件机制学习笔记录)

对于一个"我们从来不生产代码,我们只是大自然代码的搬运工"的码农来说.对android的触控机制一直是模棱两可的状态,特别是当要求一些自定义的控件和androide的自带控件(比如ViewPager,ListView,ScrollView)高度嵌套在一起使用时. 花了点时间梳理了下,做个笔记.对于一个触控的事件从用户输入到传递到Actigvity到最外层的Viewgroup在到子View,中间过程还可能穿插多个Viewgroup,android在ViewGroup提供了3个方法来控制流

深入浅出iOS事件机制

深入浅出iOS事件机制 2015年 04月 12日 本文章将讲解有关iOS事件的传递机制,如有错误或者不同的见解,欢迎留言指出.转载自:http://zhoon.github.io/ios/2015/04/12/ios-event.html iOS的事件有好几种:Touch Events(触摸事件).Motion Events(运动事件,比如重力感应和摇一摇等).Remote Events(远程事件,比如用耳机上得按键来控制手机),其中最常用的应该就是Touch Events了,基本存在于每个a