Nopcommerce 之事件機制

Nop有着完善的事件機制,在框架中也屢次用到。好比刪除刪除電子郵件時刪除指定的緩存、更新實體時,更新緩存等。這裏用到的是「生產者/消費者」模式,該模式中,定義了對象之間一對多的依賴,當一個對象改變狀態時,它的全部依賴者都會收到通知並自動更新。生產者發佈事件,消費者處理事件。緩存

一.相關接口和類:框架

1.IEventPublisher事件發佈接口。ide

2.EventPublisher實現IEventPublisher的類,主要功能包括髮布事件並通知訂閱者。函數

3.IConsumer<T>消費者(事件訂閱者)接口。this

4.ISubscriptionService訂閱者接口,解析全部的訂閱者。spa

5.SubscriptionService的具體實現。插件

二註冊事件:code

   若是用戶想要偵聽事件,就須要註冊成爲消費者。消費者接口IConsumer<T>爲一個泛型接口,裏面有一個處理事件的方法。IConsumer<T>接口代碼以下:對象

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

在該框架中,實現IConsumer<T>接口的類不少好比Nop.Admin.Infrastructure.Cache.ModelCacheEventConsumer代碼以下:blog

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」實現;

相關文章
相關標籤/搜索