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
    }
}
原文地址:https://www.cnblogs.com/swobble/p/12809970.html