Prism 5.事件聚合 Prism 5.事件聚合
Prism提供了一种基于事件聚合服务机制,允许组件之间进行发布订阅,不相互引用也能进行通讯
EventAggregator提供了多播发布订阅功能,多个发起者可以发布同一事件,多个订阅者也可以相应同一事件。
IEventAggregator接口提供了容器类服务实现发布订阅,他会在第一次连接时去实例化,所以不用去担心他的实例化
而真正工作中是用PubSubEvent类去实现发布订阅。
创建一个事件
public class TickerSymbolSelectedEvent : PubSubEvent<string>{}
发布事件
发布者通过在EventAggregator中检索事件然后发起,首先在你的构造函数中需要有一个EventAggregator,你可以通过DI去实例化它
public class MainPageViewModel
{
IEventAggregator _eventAggregator;
public MainPageViewModel(IEventAggregator ea)
{
_eventAggregator = ea;
}
}
然后发布事件
_eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish("STOCK0");
订阅事件
订阅者通过在PubSubEvent类中用Subscribe的重载方法去注册事件
public class MainPageViewModel
{
public MainPageViewModel(IEventAggregator ea)
{
ea.GetEvent<TickerSymbolSelectedEvent>().Subscribe(ShowNews);
}
void ShowNews(string companySymbol)
{
//implement logic
}
}
这里有几条原则可以让你找到最适合你的订阅事件的方式:
1 当事件接收后,你要更新UI界面的元素,你要在UI线程订阅接收事件
2 如果你是想过滤事件,当订阅时要提供一个过滤委托
3 用强类型的委托订阅事件并手动取消订阅,这将大大提高性能
4 一条都没中你就用默认的就行了
在UI线程订阅事件
有时候订阅者在接收事件后腰更新UI界面上元素,然后在WPF中,只有UI线程才能更新界面元素,
但是,一般来说,订阅者是在发布者的线程里接收事件,
如果发布者就是UI线程,那就莫问题啊,
如果发布者是在后台线程,订阅者就不能直接的更新UI了,需要调度Dispatcher去更新UI线程。
PubSubEvent提供了一个自动的方式帮助订阅者在UI线程更新界面元素
public class MainPageViewModel
{
public MainPageViewModel(IEventAggregator ea)
{
ea.GetEvent<TickerSymbolSelectedEvent>().Subscribe(ShowNews, ThreadOption.UIThread);
}
void ShowNews(string companySymbol)
{
//implement logic
}
}
ThreadOption有三类:
1 PublisherThread
2 BackgroundThread,这是一个线程池线程
3 UIThread
警告:EventAggregator必须得是UI线程定义的才可以使用自动UI线程更新界面元素
订阅过滤
订阅者不必处理发布者的所有事件,所以订阅者得有一个过滤器来筛选
这个过滤器是针对类型的
System.Predicate<T>
public class MainPageViewModel
{
public MainPageViewModel(IEventAggregator ea)
{
TickerSymbolSelectedEvent tickerEvent = ea.GetEvent<TickerSymbolSelectedEvent>();
tickerEvent.Subscribe(ShowNews, ThreadOption.UIThread, false,
companySymbol => companySymbol == "STOCK0");
}
void ShowNews(string companySymbol)
{
//implement logic
}
}
使用强类型订阅
对时间有大量事件的话,如果你对性能有要求,你可以使用强引用,如果你选择使用强引用,当你想释放订阅者的时候你就必须手动取消订阅。
默认情况下,PubSubEvent维持着一种对于定于订阅处理和过滤引用的弱委托,使用弱委托引用可以使订阅者不必取消订阅,并可以进行正确的垃圾回收。
但是弱委托比强委托要慢,如果你使用强委托,则订阅者应取消订阅以确保能垃圾回收。
在Subscribe方法内使用keepSubscriberReferenceAlive参数进行强委托
public class MainPageViewModel
{
public MainPageViewModel(IEventAggregator ea)
{
bool keepSubscriberReferenceAlive = true;
TickerSymbolSelectedEvent tickerEvent = ea.GetEvent<TickerSymbolSelectedEvent>();
tickerEvent.Subscribe(ShowNews, ThreadOption.UIThread, keepSubscriberReferenceAlive,
companySymbol => companySymbol == "STOCK0");
}
void ShowNews(string companySymbol)
{
//implement logic
}
}
keepSubscriberReferenceAlive
true:不会自动进行垃圾回收,应该手动取消订阅
false:默认值,没有引用的话就会自动垃圾回收并自动取消订阅
取消订阅事件
两种方式:
1 取消订阅处理
public class MainPageViewModel
{
TickerSymbolSelectedEvent _event;
public MainPageViewModel(IEventAggregator ea)
{
_event = ea.GetEvent<TickerSymbolSelectedEvent>();
_event.Subscribe(ShowNews);
}
void Unsubscribe()
{
_event.Unsubscribe(ShowNews);
}
void ShowNews(string companySymbol)
{
//implement logic
}
}
2 通过Subscribe方法返回值-订阅token来取消订阅
public class MainPageViewModel
{
TickerSymbolSelectedEvent _event;
SubscriptionToken _token;
public MainPageViewModel(IEventAggregator ea)
{
_event = ea.GetEvent<TickerSymbolSelectedEvent>();
_token = _event.Subscribe(ShowNews);
}
void Unsubscribe()
{
_event.Unsubscribe(_token);
}
void ShowNews(string companySymbol)
{
//implement logic
}
}