本节学习了Event Aggregation事件聚合,这个在Prism中很重要,特别是对于Module间的通信。除了前面介绍的Command可以用于模块间的通信,还有我们这一节介绍的Event Aggregation(事件聚合).
(一)为什么不用.NET FrameWork中的事件呢?
使用.NET Framework事件是罪简单和直观的方式用于非松散耦合需求的组件,属于对象引用依赖的发布-订阅模型
(二) EventAggregator事件聚合器
提供了多点传送发布/订阅功能。这意味着可能有可以触发同一事件多个发布者和可以监听同一事件的订阅者。
(三)模块间通信过程简介
CompositePresentationEvent<TPayload>类实例实现了事件的订阅和取消,而IEventAggregator实例用来获取接收CompositePresentationEvent<TPayload>类实例.IEventAggregator实例在每个模块中含有,这样模块间就可以通信了。
(四)下面贴出Prism中Event Aggregation QuickStart的部分代码:
(1)创建了 CompositePresentationEvent<TPayload>类
在项目中EventAggregation.Infrastructure.Silverlight的FundAddedEvent.cs代码中,
//定义CompositePresentationEvent<TPayload>类 //(1)该类是泛型类:强制发布者和订阅者要一种正确的类型实现 发布-订阅连接 //(2)是唯一继承自EventBase的类 //(3)因为CompositePresentationEvent<TPayload>往往被多个模块公用,所以要单独于 // 其他的模块新建类库项目 //FundOrder是这里的TPayLoad类型 public class FundAddedEvent : CompositePresentationEvent<FundOrder> { }
(2)事件的发布
在ModuleA.Silverlight项目中的
public class AddFundPresenter { private IAddFundView _view; //IEventAggregator 事件聚合器接口 private IEventAggregator eventAggregator; public AddFundPresenter(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; } //事件发布:当用户添加一个fund基金,事件就被发布 //发布者发布一个事件 //(1)通过IEventAggregator的实例eventAggregator的Publish方法 //(2)指定GetEvent<TEventType>中TEventType为FunAddedEvent void AddFund(object sender, EventArgs e) { FundOrder fundOrder = new FundOrder(); fundOrder.CustomerId = View.Customer; fundOrder.TickerSymbol = View.Fund; if (!string.IsNullOrEmpty(fundOrder.CustomerId) && !string.IsNullOrEmpty(fundOrder.TickerSymbol)) eventAggregator.GetEvent<FundAddedEvent>().Publish(fundOrder); } public IAddFundView View { get { return _view; } set { _view = value; _view.AddFund += AddFund; } } }
(3)事件的订阅
在ModuleB.Silverlight项目中的ActivityPresenter.cs中
public class ActivityPresenter { private string _customerId; private IEventAggregator eventAggregator; private SubscriptionToken subscriptionToken; public ActivityPresenter(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; } public void FundAddedEventHandler(FundOrder fundOrder) { Debug.Assert(View != null); View.AddContent(fundOrder.TickerSymbol); } public bool FundOrderFilter(FundOrder fundOrder) { return fundOrder.CustomerId == _customerId; } public IActivityView View { get; set; } public string CustomerId { get { return _customerId; } set { _customerId = value; FundAddedEvent fundAddedEvent = eventAggregator.GetEvent<FundAddedEvent>(); if (subscriptionToken != null) { fundAddedEvent.Unsubscribe(subscriptionToken); } //订阅事件 //(1)获取事件聚合器实例 //(2)调用Subscribe方法 // Subscribe方法重载,有不同的作用 // Action<T>: 泛型委托 // ThreadOption:当为PublisherThread时(默认值)能获取发布者线程 // BackgroundThread时 从.NET Framework线程池上异步获取事件 // UIThread时 获取事件从UI线程上。 // keepSubscriberReferenceAlive: 当为true 事件实例是强引用订阅者,因此不能垃圾回收 // 当为false(默认值)弱引用订阅者,因此当没有其他引用时允许垃圾回收释放订阅者实例,当订阅者实例被回收,事件自动取消订阅 subscriptionToken = fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, false, FundOrderFilter); //lamda表达式写法 //subscriptionToken = fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, false, FunOrder => FunOrder.CustomerId == this._customerId); View.SetTitle(string.Format(CultureInfo.CurrentCulture, Resources.ActivityTitle, CustomerId)); } } }
(1)获取事件聚合器实例
(2)调用Subscribe方法
Subscribe方法重载,有不同的作用
Action<T>: 泛型委托
ThreadOption:
当为PublisherThread时(默认值)能获取发布者线程
BackgroundThread时 从.NET Framework线程池上异步获取事件
UIThread时 获取事件从UI线程上。
keepSubscriberReferenceAlive: 当为true 事件实例是强引用订阅者,因此不能垃圾回收
当为false(默认值)弱引用订阅者,因此当没有其他引用时允许垃圾回收释放订阅者实例,当订阅者实例被回收,事件自动取消订阅