Prism、CM和Jounce里都有各自的事件通信机制,也都叫EventAggregator。
相比于Prism,Jounce里的EventAggregator的风格更接近CM。当然作者也是这么说的:The pattern here is based on the lightweight version Rob Eisenburg introduced with Caliburn Micro。
这里涉及的类主要有三个:两个接口类IEventAggregator和IEventSink<in T>,还有实现IEventAggregator的EventAggregatorService。
IEventAggregator定义了四个方法,其中三个是订阅消息、在UI线程上订阅消息和取消订阅,接受的参数都是IEventSink;最后一个方法是用来发布消息的。
EventAggregatorService内部维护了一个弱引用的字典用来存储订阅了消息的IEventSink,当在某个地方谁谁谁发布消息的时候,就会在这个字典里去找泛型类型匹配的IEventSink并调用其唯一的一个方法HandleEvent。
其实就是观察者,你懂的。
来实例操作下,通过模板新建解决方案,整个结构如下:
MainPage分为左右2个部分,分别用来存放PublishIntSubscribeGuid和PublishGuidSubscribeInt。
PublishIntSubscribeGuid会发布Int值,然后接收Guid的消息。
PublishGuidSubscribeInt会发布Guid,然后接收Int值的消息。
两个页面都是上面一个按钮,下面一个TextBox用来显示收到的消息,后台代码也差不多,我们来看看其中一个:
[Export]
public partial class PublishIntSubscribeGuid : UserControl, IEventSink<Guid>, IPartImportsSatisfiedNotification
{
[Import]
public IEventAggregator EventAggregator { get; set; }
public PublishIntSubscribeGuid()
{
InitializeComponent();
this.PublishButton.Click += new RoutedEventHandler(PublishButton_Click);
}
void PublishButton_Click(object sender, RoutedEventArgs e)
{
var random = new Random();
this.EventAggregator.Publish(random.Next());
}
#region IPartImportsSatisfiedNotification 成员
public void OnImportsSatisfied()
{
EventAggregator.SubscribeOnDispatcher(this);
}
#endregion
#region IEventSink<Guid> 成员
public void HandleEvent(Guid publishedEvent)
{
this.OutTextBox.Text += "\r\n" + publishedEvent;
}
#endregion
}
首先,要订阅Guid类型的消息先要实现IEventSink接口,泛型类型是Guid。
然后,要实现IPartImportsSatisfiedNotification接口,在MEF导入IEventAggregator后,注册完成消息订阅(这里在UI线程上订阅),这样当有某个地方发布类型是GUID的消息时,HandleEvent(Guid publishedEvent)方法就会最终被调用。
另外,在点击发布消息的按钮时候发布个随机的Int值,当某个地方订阅了Int类型的消息时,那个地方就会接收到这个随机值。
实际应用可能要复杂点,泛型会是某个实体类或者某种错误等等。
看一下效果:
代码:这里
PS:
1.打开APP.CS,可以看到通过模板创建的解决方案默认使APP实现了 IEventSink<UnhandledExceptionEvent>接口,这个就是原来通过Application.Current.UnhandledException注册的系统未处理错误,Jounce在ApplicationService里进行了注册和转换并通过事件系统进行了发布。这样就可以在别的地方也进行侦听。
2.整个事件通信系统是Jounce页面加载和导航的基础,可以实现IEventSink<ViewNavigationArgs>并侦听下看看。