从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 }
参考资料: