RSS

导航







快速搜索

高级搜索 »

注意:此页面是Unity 1.x 中文文档的一部分。

事件截获扩散的快速入门向你展示了如何通过添加用户扩展的方式来扩展你的 Unity 容器快速入门通过对容器功能的扩展来实现事件截获,在交通灯的应用程序里演示了新的扩展,交通灯的讨论见:漫游:Unity StopLight 快速入门

事件截获扩展的快速入门包含一下3个项目
  • EventBroker。该项目实现了一个简单的支持多事件的发布和订阅功能。
  • EventBrokerExtension。该项目允许在应用程序种使用自定义的容器扩展来发布和订阅事件。
  • StopLight。该项目和 Unity StopLight 快速入门相同,但是这里它使用了自定义的用户容器来管理事件的发布和订阅。

关于用户容器扩散的更多信息,请参见创建容器扩展使用容器扩展

图1显示了事件截获的类关系图

图1 EventBroker 扩展快速入门的架构、类和结构

图1 EventBroker 扩展快速入门的架构、类和结构


如果您在 漫游:Unity StopLight 快速入门 章节的快速入门中中比较过例子的结构,你可以看到事件捕获扩展的快速入门有如下功能:
  • Program类在容器组件中注册了类型的映射,并且调用Resolve 方法来实例化StopLight 窗体,并且将SimpleEventBrokerExtension 添加至容器组件中。
  • SimpleEventBrokerExtension继承自UnityContainerExtension 基类,创建了EventBroker类的实例,EventBroker类发布和订阅了分布式事件。
  • EventBroker 类创建了PublishedEvent 类的实例,PublishedEvent 类则为维护事件订阅队列和事件订阅者提供了一个操作的方式。
  • StopLightPresenter,StopLightSchedule和RealTimeTimer 类用SimpleEventBrokerExtension类 为事件订阅者和事件发布提供了一些特性。

事件捕获的扩展入门显示了 Unity 块和自定义容器扩展机制
  • 创建自定义Unity 容器的扩展
  • 在运行时将扩展加入到Unity 容器
  • 使用事件捕获的扩展范例

创建自定义Unity 容器的扩展

自定义Unity 容器扩展是一个从 UnityContainerExtension 基类继承而来并且实现了一些额外的方法的自定义类型。该扩展可以访问容器,并且可以接收到容器中已经注册的事件.这里将着重描述EventBrokerExtension 中的一些特征。

SimpleEventBrokerExtension 类继承 UnityContainerExtension ,它从SimpleEventBroker 工程文件中创建了一个新的EventBroker 类对象,然后覆写了UnityContainerExtension 基类的Initialize 方法

SimpleEventBrokerExtension 中Initialize 方法代码如下,添加一个新的 EventBroker ,该 EventBroker 创建到容器的 Locator,以便其他的类能够轻易的定位并引用他,然后他向 Unity 管道添加了2个策略.他向 PreCreation 添加一个反射策略,这样他就能够检查到2个特性,该特性将由扩展使用(他们是 PublishesAttribute 和SubscribesToAttribute),此外他还添加了一个绑定策略到 Initialization,该策略用来注册一些订阅者和发布者,但是订阅者和发布者必须是由 EventBroker 代理类注册的

C#
public class SimpleEventBrokerExtension : UnityContainerExtension,
                                          ISimpleEventBrokerConfiguration
{
  private EventBroker broker = new EventBroker();

  protected override void Initialize()
  {
    Context.Locator.Add(typeof(EventBroker), broker);
    Context.Strategies.AddNew<EventBrokerReflectionStrategy>(UnityBuildStage.PreCreation);
    Context.Strategies.AddNew<EventBrokerWireupStrategy>(UnityBuildStage.Initialization);
  }

  public EventBroker Broker
  {
    get { return broker; }
  }
}

Visual Basic
Public Class SimpleEventBrokerExtension
    Inherits UnityContainerExtension
    Implements ISimpleEventBrokerConfiguration

  Private _broker As New EventBroker()

  Protected Overloads Overrides Sub Initialize()
    Context.Locator.Add(GetType(EventBroker), _broker)
    Context.Strategies.AddNew(Of EventBrokerReflectionStrategy)(UnityBuildStage.PreCreation)
    Context.Strategies.AddNew(Of EventBrokerWireupStrategy)(UnityBuildStage.Initialization)
  End Sub

  Public ReadOnly Property Broker() As EventBroker _
         Implements ISimpleEventBrokerConfiguration.Broker 
    Get
      Return _broker
    End Get
  End Property

End Class
EventBroker 类提供了Dictionary ,用来包含全部的事件名到发布者的映射,并且暴露了一些注册发布者和订阅者的方法,(方法是RegisterPublisher 和RegisterSubscriber)。他也暴露了一些用于特定的事件的反注册方法.这些方法的发部分功能全部在PublishedEvent 类里,该类保存,暴露了所有的发布者和订阅者队列

在前一个队列里的Initialize 的方法里,通过调用EventBroker 类的RegisterPublisher方法 和RegisterSubscriber 方法,wire-up 策略通过Initialize 被添加到Unity .这就是说当Unity 发现PublishesAttribute 和SubscribesToAttribute 特性的时候,他会在EventBroker自动注册类或者类的成员使他成为个发布者或者订阅者。

如果注册成为一个发布者,EventBroker 则调用PublishedEvent 类的AddPublisher 方法,该方法将添加一个新的的发布者到发布者队列之中,并且为发布的事件连接到一个名叫OnPublisherFiring 的事件处理方法.所以当发布者发布事件的时候,PublishedEvent 类中的事件处理方法将通过订阅者队列的事件订阅代理调用每一个方法来做出事件对应的反应.代码如下

C#
private void OnPublisherFiring(Object sender, EventArgs e)
{
  foreach(EventHandler subscriber in subscribers)
  {
    subscriber(sender, e);
  }
}

Visual Basic
Private Sub OnPublisherFiring(sender As Object, e As EventArgs)
  For Each subscriber As EventHandler in _subscribers
    subscriber.Invoke(sender, e)
  Next
End Sub
在运行时将扩展加入到Unity 容器

在您创建了一个自定义容器扩展以后,你需要把他添加到Unity 容器.您可以通过编译并且指定一个类型和程序集的名称,然后写入配置文件.详细配置,请参见 Entering Configuration Information.

但是,事件截获扩展的快速入门通过调用Unity 容器类的一个方法,将自定义的SimpleEventBrokerExtension 类型在运行的时候添加到容器中.交通灯例子中Program 类初始化应用程序,并且载入一个主窗体,他建立了一个新的Unity容器的实例,并且注册了相关的映射类型到 ILogger 和 IStoplightTimer .他体内哦各样调用了AddNewExtension 方法,指定了SimpleEventBrokerExtension 类.代码如下

C#
IUnityContainer container = new UnityContainer()
           .AddNewExtension<SimpleEventBrokerExtension>()
           .RegisterType<ILogger, TraceLogger>()
           .RegisterType<IStoplightTimer, RealTimeTimer>();

Visual Basic
Dim container As IUnityContainer = New UnityContainer() _
           .AddNewExtension(Of SimpleEventBrokerExtension)() _
           .RegisterType(Of ILogger, TraceLogger)() _
           .RegisterType(Of IStoplightTimer, RealTimeTimer)()

使用事件捕获的扩展范例

正如图1中所显示的,事件捕获扩展快速入门使用了自定义的SimpleEventBrokerExtension 容器来实现 2 个事件的发布和接收;

  • RealTimeTimer类发布TimerTick 事件,该事件在计数器变成零的时候产生这个事件,StoplightSchedule 类订阅这个事件.在事件处理中,他更新lightTimes 数组中的索引(TimeSpan 数组保存了不同颜色的时间段),并设置交通灯的时间,然后再次重新计时.
  • StoplightSchedule类发布ChangeLight 事件,该事件在时间段改变和计数器重新计数之前发生.StoplightPresenter 类是该事件订阅者.在事件处理中,StoplightPresent调用 StopLight 类的Next方法来改变交通等待颜色,并且将信息写入TraceLogger.

为了能显示他发布的TimerTick 事件,RealTimeTimer 类使用Publishes 特性,指定发布事件的名称,代码如下

C#
[Publishes("TimerTick")]
public event EventHandler Expired;
private void OnTick(Object sender, EventArgs e)
{
  timer.Stop();
  OnExpired(this);
}

Visual Basic
<Publishes("TimerTick")> _
Public Event Expired As EventHandler Implements IStoplightTimer.Expired
Private Sub OnTick(sender As Object, e As EventArgs)
  timer.Stop()
  OnExpired(Me)
End Sub

OnExpired 方法将简单的检查当事件发出的是是否存在处理方法,如下所示。

C#
protected virtual void OnExpired(object sender)
{
  EventHandler handlers = Expired;
  if(handlers != null)
  {
    handlers(this, EventArgs.Empty);
  }
}

Visual Basic
Protected Overridable Sub OnExpired(ByVal sender As Object)
  Dim handlers As EventHandler = ExpiredEvent
  If Not handlers Is Nothing Then
    RaiseEvent Expired(Me, EventArgs.Empty)
  End If
End Sub

StoplightSchedule 类通过SubscribesTo 特性订阅TimerTick 事件

C#
[SubscribesTo("TimerTick")]
public void OnTimerExpired(Object sender, EventArgs e)
{
  EventHandler handlers = ChangeLight;
  if(handlers != null)
  {
    handlers(this, EventArgs.Empty);
  }
  currentLight = ( currentLight + 1 ) % 3;
  timer.Duration = lightTimes[currentLight];
  timer.Start();
}

Visual Basic
<SubscribesTo("TimerTick")> _
Public Sub OnTimerExpired(ByVal sender As Object, ByVal e As EventArgs)
  Dim handlers As EventHandler = ChangeLightEvent
  If Not handlers Is Nothing Then
    RaiseEvent ChangeLight(Me, EventArgs.Empty)
  End If
  currentLight = ( currentLight + 1 ) Mod 3
  _timer.Duration = lightTimes(currentLight)
  _timer.Start()
End Sub

前面的代码表明当他接收到 TimerTick 事件的时候OnTimerExpired 事件处理产生了ChangeLight 事件.ChangeLight 是当前事件的名称,但是 StoplightSchedule 类同样发布该名称的事件
C#
[Publishes("ChangeLight")]
public event EventHandler ChangeLight;

Visual Basic
<Publishes("ChangeLight")> _
Public Event ChangeLight As EventHandler

最后StoplightPresenter类通过事件处理OnScheduledLightChange订阅了ChangeLight 事件.在该事件处理中,他调用StopLight 的Next 方法,代码如下

C#
[SubscribesTo("ChangeLight")]
public void OnScheduledLightChange(Object sender, EventArgs e)
{
  stoplight.Next();
}

Visual Basic
<SubscribesTo("ChangeLight")> _
Public Sub OnScheduledLightChange(ByVal sender As Object, ByVal e As EventArgs)
  _stoplight.Next()
End Sub

本章的代码实例向您展示了自定义SimpleEventBrokerExtension 在分布式事件中的用法,并且指导您在使用Unity 生成应用程序类中的实体时他如何发布和订阅事件

顶部
.NET 藏经阁 | | 版权所有 ©2008 entlib.net.cn