事件聚合器
EventAggregator是一个去中心化的、弱绑定的、基于发布/订阅的事件管理器。
发布者和订阅者
订阅者
对特定事件感兴趣的订阅服务器可以告诉IEventAggregator他们的兴趣,并且每当发布者将该特定事件发布到IEventAgenerator时,订阅服务器都会收到通知。
事件就是类——用它们做任何你想做的事。例如:
class MyEvent {
// Do something
}
订阅服务器必须实现IHandle<T>
,其中T
是他们感兴趣接收的事件类型(当然,他们可以为多个T
实现多个IHandle<T>
)。然后,他们必须获得IEventAggregator的实例,并自行订阅,例如:
class Subscriber : IHandle<MyEvent>, IHandle<MyOtherEvent>
{
public Subscriber(IEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this);
}
public void Handle(MyEvent message)
{
// ...
}
public void Handle(MyOtherEvent message)
{
// ...
}
}
对于VB.NET用户来说,通过引用传递eventAggregator的Sub New()
可能会在命名空间中失败,并且必须对每个新订阅者进行定义可能会让人恼火。因此,在全局模块中定义eventAggregator,然后直接订阅它,而不是将其引用传递给您调用的每个新ViewModel,这可能会更容易。
Module Global
Public eventAggregator as IEventAggregator
End Module
Class Subscriber : Implements IHandle(Of MyEvent)
Public Sub New()
Global.eventAggregator.Subscribe(Me)
End Sub
'Public Sub Handle...
End Class
确保模块的名称空间为空,以便可以在整个程序中使用它。
发布者
发布者还必须获得IEventAggregator的一个实例,但他们不需要自己订阅——他们只需要调用IEventAgenerator。每次发布事件时都要发布,例如:
class Publisher
{
private IEventAggregator eventAggregator;
public Publisher(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public void PublishEvent()
{
this.eventAggregator.Publish(new MyEvent());
}
}
同样,对于VB.NET用户,如果您已经设置了全局模块,则不需要将eventAggregator传递给发布服务器。您可以直接发布到全局事件聚合器;
Class Publisher
Public Sub PublishEvent()
Global.eventAggregator.Publish(New MyEvent())
End Sub
End Class
取消订阅和弱绑定
因为IEventAggregator是弱绑定的,订阅者不需要自己取消订阅——IEventAgenerator不会保留他们。然而,如果用户想取消订阅,也可以取消订阅-call
IEventAggregator.Unsubscribe(this);
同步和异步发布
默认的IEventAggregator.Publish
方法同步发布事件。您也可以调用PublishOnUIThread
以异步调度到UI线程,或者调用PublishWithDispatcher
并传递您想作为调度器的任何操作(如果在IEventAggregator上编写自己的方法,这可能很有用)。
通道
订阅服务器可以收听特定通道,发布服务器可以将事件发布到特定通道。如果事件发布到特定通道,则只有订阅了该通道的订阅者才会收到该事件。如果在几个不同的上下文中使用相同的消息类型,这可能很有用。
通道是字符串,因此允许某个通道的订阅者和该通道的发布者之间的松散耦合。
默认情况下,Subscribe()
会将订阅者订阅到单个通道EventAggregator.DefaultChannel
。类似地,Publish()
(及其所有变体)会将事件发布到同一默认通道。但是,如果需要,您可以指定自己的频道。。。。
订阅频道
要订阅特定频道,请将其作为参数传递给Subscribe:eventAggregator.Subscribe(this,“ChannelA”)
。您还可以订阅多个频道:eventAggregator.Subscribe(this,“ChannelA”、“ChannelB”)
。
在这两种情况下,您都不会订阅EventAggregator.DefaultChannel
,只订阅列出的通道。您将只收到推送到“通道A”或“通道B”的事件。
发布通道
若要发布到特定通道,请将其作为参数传递给Publish:eventAggregator.Publish(message,“ChannelA”)
或eventAggregationor.PublishOnUIThread(message,”ChannelA“,”ChanelB“)
等。与上面的订阅一样,事件将发布到所有命名的频道,而不是默认频道。
取消订阅通道
要取消订阅通道,请将其传递给取消订阅Unsubscribe: eventAggregator.Unsubscribe(this, "ChannelA")
。您将继续订阅以前订阅的任何其他通道,并且没有取消订阅。
调用eventAggregator.Unsubscribe(this)
将取消订阅所有频道。
使用您自己的IoC容器
如果您将StyletIoC与默认Bootstrapper<TRootViewModel>
一起使用,则无需担心这一点-EventAggregator默认设置正确。
然而,如果您使用的是另一个IoC容器,则需要确保EventAggregator已注册为接口IEventAggregator
-始终只能创建一个EventAggregate实例,并且每次请求时都必须返回此实例。