Prism V2之旅(6)

来源:互联网 发布:php w3cschool 编辑:程序博客网 时间:2024/06/09 14:18

     这篇来讲事件.事件主要用来交互.

监听事件

 

订阅了一些blog的rss,如果我订阅的blog发布了新的文章的话,系统(就是抓虾)就会帮我抓取新的rss信息

image

很好理解,一方订阅(Subscribe),一方发布(Publish).

prism的事件

 

prism的抽象类EventBase实现了事件的订阅和发布的操作.CompositePresentationEvent类继承自EventBase做了进一步封装,其是一个泛型类,我们可以通过CompositePresentationEvent来传递一个参数.

image

 

下面是一个简单的示例,记得先调用Subscribe方法订阅事件,然后调用Publish方法来发布,同时也可以调用Unsubscribe方法来取消订阅

private void SubscribeAndRaiseEvent(){    CompositePresentationEvent<string> compositePresentationEvent = new CompositePresentationEvent<string>();    var action = new Action<string>((str) =>    {        System.Windows.MessageBox.Show(str);    });    compositePresentationEvent.Subscribe(action);    compositePresentationEvent.Publish("hello");    compositePresentationEvent.Unsubscribe(action);    compositePresentationEvent.Publish("hello");}

 

多重订阅,可以订阅多个事件

 

private void MultipleSubscribersAndRaiseCustomEvent(){    CompositePresentationEvent<string> compositePresentationEvent = new CompositePresentationEvent<string>();    var actionOne = new Action<string>((str) =>    {        System.Windows.MessageBox.Show(str);    });    var actionTwo = new Action<string>((str) =>    {        System.Windows.MessageBox.Show(str);    });    compositePresentationEvent.Subscribe(actionOne);    compositePresentationEvent.Publish("hello");    compositePresentationEvent.Unsubscribe(actionTwo);    compositePresentationEvent.Publish("world");}

 

事件聚合模块交互

 

上面代码为示例,效果与.net内置的事件相似,只是做法不同而已,这样的话没多大意义,如果不同模块之间需要交互,那么事件就起作用了.

所以就需要一个容器来保存事件的状态,prism的IEventAggregator接口便是这样设计的

当事件被订阅的事件,IEventAggregator的GetEvent方法,该方法是一个泛型方法,传入的参数必须继承自EventBase,

该方法会先实例化这个类,所以我们不可以出现这样的代码

private void CustomEventWithEventAggregator(){    eventAggregator.GetEvent<CompositePresentationEvent<string>>();}

 

正确的做法是从CompositePresentationEvent派生一个类,如

private void CustomEventWithEventAggregator(){    var action = new Action<string>((str) =>    {        System.Windows.MessageBox.Show(str);    });    eventAggregator.GetEvent<CustomEvent>().Subscribe(action);    eventAggregator.GetEvent<CustomEvent>().Publish("hello");}public class CustomEvent : CompositePresentationEvent<string>{}

 

以上代码为演示,你只需要明确定义Event的类型,就可以在不同模块交互.两个模块之间就不要相互引用,降低了耦合度.

事件的回调方式

 

当事件回调时(即事件被触发时),有三种方式.

1.同步线程 该怎么处理就怎么处理,默认情况下是以这种方式来处理的

2.在UI线程上触发,即调用了wpf Dispatcher的BeginInvoke方法

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method, arg);

3.在后台线程上异步调用,即通过BackgroundWorker类来异步操作

public override void InvokeAction(Action<TPayload> action, TPayload argument){    BackgroundWorker worker = new BackgroundWorker();    worker.DoWork += ((sender, e) => action((TPayload)e.Argument));    //handle worker.RunWorkerCompleted and log exceptions?    worker.RunWorkerAsync(argument);}

 

这三种方式是由ThreadOption枚举来设定的

image

这便是CompositePresentationEvent类扩展的功能之一,如下代码

public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter){    IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive);    IDelegateReference filterReference;    if (filter != null)    {        filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive);    }    else    {        filterReference = new DelegateReference(new Predicate<TPayload>(delegate { return true; }), true);    }    EventSubscription<TPayload> subscription;    switch (threadOption)    {        case ThreadOption.PublisherThread:            subscription = new EventSubscription<TPayload>(actionReference, filterReference);            break;        case ThreadOption.BackgroundThread:            subscription = new BackgroundEventSubscription<TPayload>(actionReference, filterReference);            break;        case ThreadOption.UIThread:            subscription = new DispatcherEventSubscription<TPayload>(actionReference, filterReference, UIDispatcher);            break;        default:            subscription = new EventSubscription<TPayload>(actionReference, filterReference);            break;    }    return base.InternalSubscribe(subscription);}

 

弱引用还是强引用?


通过上面的代码,我们看到该方法还有一个参数keepSubscriberReferenceAlive,默认值是false,就是弱引用了,如果你设置成强引用,记得在不需要事件的时候,取消事件的订阅.

事件过滤


Subscribe方法最后一个方法是filter事件过滤器,

举个例子我订阅了某某技术牛人的rss,平时他都写一些技术文章,可他也喜欢写了一些与技术无关的文章,我不想看,并不是他发布什么内容我都接受的,我是要有所选择的,我要把这些内容过滤掉.这个功能比较好.平时看报纸就没这个功能:).

上面的解释就是事件过滤器的功能.

 

事件在v2的改动不是很大,大家也可以参考这篇,有重复了,这篇就到这里

原创粉丝点击