• 从Prism中学习设计模式之Event Aggregator 模式


    Event Aggregator 模式定义:渠道事件从多个对象通过一个单一的对象来简化clients的注册。

    结构图:

    Prism的Event Aggregator 模式:Event Aggregator允许多对象定位和发布、订阅事件。

    我们从Prism源代码中的EventAggregator和CompositePresentationEvent可以学习它是如何管理和传递事件消息的。

      1     public interface IEventAggregator
      2     {
      3         TEventType GetEvent<TEventType>() where TEventType : EventBase, new();
      4     }
      5 
      6     public class EventAggregator : IEventAggregator
      7     {
      8         private readonly Dictionary<Type, EventBase> events = new Dictionary<Type, EventBase>();
      9 
     10         public TEventType GetEvent<TEventType>() where TEventType : EventBase, new()
     11         {
     12             EventBase existingEvent = null;
     13 
     14             if (!this.events.TryGetValue(typeof(TEventType), out existingEvent))
     15             {
     16                 TEventType newEvent = new TEventType();
     17                 this.events[typeof(TEventType)] = newEvent;
     18 
     19                 return newEvent;
     20             }
     21             else
     22             {
     23                 return (TEventType)existingEvent;
     24             }
     25         }
     26     }
     27 
     28   public class CompositePresentationEvent<TPayload> : EventBase
     29     {
     30         private IDispatcherFacade uiDispatcher;
     31 
     32         private IDispatcherFacade UIDispatcher
     33         {
     34             get
     35             {
     36                 if (uiDispatcher == null)
     37                 {
     38                     this.uiDispatcher = new DefaultDispatcher();
     39                 }
     40 
     41                 return uiDispatcher;
     42             }
     43         }
     44 
     45         public SubscriptionToken Subscribe(Action<TPayload> action)
     46         {
     47             return Subscribe(action, ThreadOption.PublisherThread);
     48         }
     49 
     50         public SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption)
     51         {
     52             return Subscribe(action, threadOption, false);
     53         }
     54 
     55         public SubscriptionToken Subscribe(Action<TPayload> action, bool keepSubscriberReferenceAlive)
     56         {
     57             return Subscribe(action, ThreadOption.PublisherThread, keepSubscriberReferenceAlive);
     58         }
     59 
     60         public SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive)
     61         {
     62             return Subscribe(action, threadOption, keepSubscriberReferenceAlive, null);
     63         }
     64 
     65         public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter)
     66         {
     67             IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive);
     68             IDelegateReference filterReference;
     69             if (filter != null)
     70             {
     71                 filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive);
     72             }
     73             else
     74             {
     75                 filterReference = new DelegateReference(new Predicate<TPayload>(delegate { return true; }), true);
     76             }
     77             EventSubscription<TPayload> subscription;
     78             switch (threadOption)
     79             {
     80                 case ThreadOption.PublisherThread:
     81                     subscription = new EventSubscription<TPayload>(actionReference, filterReference);
     82                     break;
     83                 case ThreadOption.BackgroundThread:
     84                     subscription = new BackgroundEventSubscription<TPayload>(actionReference, filterReference);
     85                     break;
     86                 case ThreadOption.UIThread:
     87                     subscription = new DispatcherEventSubscription<TPayload>(actionReference, filterReference, UIDispatcher);
     88                     break;
     89                 default:
     90                     subscription = new EventSubscription<TPayload>(actionReference, filterReference);
     91                     break;
     92             }
     93 
     94 
     95             return base.InternalSubscribe(subscription);
     96         }
     97 
     98         public virtual void Publish(TPayload payload)
     99         {
    100             base.InternalPublish(payload);
    101         }
    102 
    103         public virtual void Unsubscribe(Action<TPayload> subscriber)
    104         {
    105             lock (Subscriptions)
    106             {
    107                 IEventSubscription eventSubscription = Subscriptions.Cast<EventSubscription<TPayload>>().FirstOrDefault(evt => evt.Action == subscriber);
    108                 if (eventSubscription != null)
    109                 {
    110                     Subscriptions.Remove(eventSubscription);
    111                 }
    112             }
    113         }
    114 
    115         public virtual bool Contains(Action<TPayload> subscriber)
    116         {
    117             IEventSubscription eventSubscription;
    118             lock (Subscriptions)
    119             {
    120                 eventSubscription = Subscriptions.Cast<EventSubscription<TPayload>>().FirstOrDefault(evt => evt.Action == subscriber);
    121             }
    122             return eventSubscription != null;
    123         }
    124 
    125     }
    • 订阅
    • 取消订阅
    • 发布
    • 比较定位

    简单用法:

     1 public class Model{
     2     private readonly IEventAggregator eventAggregator;
     3 
     4     this.eventAggregator = eventAggregator;
     5     this.eventAggregator.GetEvent<UpdatedEvent>().Subscribe(this.Updated, ThreadOption.UIThread);
     6 
     7         private void Updated()
     8         {
     9             //Todo Something
    10         }
    11 
    12 }
    13 
    14     public class UpdatedEvent: CompositePresentationEvent<IDictionary<string, decimal>>
    15     {
    16     }            

     参考资料:

    http://www.martinfowler.com/eaaDev/EventAggregator.html

  • 相关阅读:
    向量、矩阵常用范数
    关于HP M451网络连接的资料
    pyqt程序最小化到系统托盘(未测试)
    博客园美化大集合2020最新!不用担心失效问题!
    添加QQ聊天
    关于加密
    python抓取谷歌学术关键词下文章题目
    如何确定网站可否可爬取
    灵狐浏览器
    利用beautifulsoup进行对标签的二次查找-以打印网易云歌单内容为例
  • 原文地址:https://www.cnblogs.com/tmywu/p/3033906.html
Copyright © 2020-2023  润新知