2009年9月30日星期三

完整演示通过Delegate实现事件event的发布和接收

创建一个Clock类,并通过事件-event通知潜在的事件订阅者,每当经过一秒就通知一次。

/*
* 类 Clock   发布事件
* 代理类型 SecondChangeHandler -----<1>
* event 型的代理实例 SecondChange -----<2>
* 成员函数 OnSecondChange 产生事件,内部调用SecondChange
* 成员函数 Run,通过一个无限循环每经过一秒调用一次OnSecondChange,产生事件。
*
*  类 DisplayClock 接收事件并通过代理执行事件句柄
*    成员函数 Subscribe 将事件接收句柄函数通过SecondChangeHandler---<1> 传递个给 事件实例SecondChange---<2>
* 成员函数 TimeHasChanged 接收句柄函数 作为SecondChangeHandler---<1>的参数
*
* 类 LogClock 接收事件并通过代理执行事件句柄 和 DisplayClock 结构完全一致。
*
* 测试例程
* 创建接收事件的实例,并让他接收Subscribe 类Clock的实例。
*
*
*/
using System;
using System.Threading;

namespace SecondChangeEvent
{
/* ======================= Event Publisher =============================== */

// Our subject -- it is this class that other classes
// will observe. This class publishes one event:
// SecondChange. The observers subscribe to that event.
public class Clock
{
// Private Fields holding the hour, minute and second
private int _hour;
private int _minute;
private int _second;

// The delegate named SecondChangeHandler, which will encapsulate
// any method that takes a clock object and a TimeInfoEventArgs
// object as the parameter and returns no value. It's the
// delegate the subscribers must implement.
public delegate void SecondChangeHandler(
object clock,
TimeInfoEventArgs timeInformation
);

// The event we publish
public event SecondChangeHandler SecondChange;

// The method which fires the Event
protected void OnSecondChange(
object clock,
TimeInfoEventArgs timeInformation
)
{
// Check if there are any Subscribers
if (SecondChange != null)
{
// Call the Event
SecondChange(clock, timeInformation);
}
}

// Set the clock running, it will raise an
// event for each new second
public void Run()
{
for (; ; )
{
// Sleep 1 Second
Thread.Sleep(1000);

// Get the current time
System.DateTime dt = System.DateTime.Now;

// If the second has changed
// notify the subscribers
if (dt.Second != _second)
{
// Create the TimeInfoEventArgs object
// to pass to the subscribers
TimeInfoEventArgs timeInformation =
new TimeInfoEventArgs(
dt.Hour, dt.Minute, dt.Second);

// If anyone has subscribed, notify them
OnSecondChange(this, timeInformation);
}

// update the state
_second = dt.Second;
_minute = dt.Minute;
_hour = dt.Hour;

}
}
}

// The class to hold the information about the event
// in this case it will hold only information
// available in the clock class, but could hold
// additional state information
public class TimeInfoEventArgs : EventArgs
{
public TimeInfoEventArgs(int hour, int minute, int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}
public readonly int hour;
public readonly int minute;
public readonly int second;
}

/* ======================= Event Subscribers =============================== */

// An observer. DisplayClock subscribes to the
// clock's events. The job of DisplayClock is
// to display the current time
public class DisplayClock
{
// Given a clock, subscribe to
// its SecondChangeHandler event
public void Subscribe(Clock theClock)
{
theClock.SecondChange +=
new Clock.SecondChangeHandler(TimeHasChanged);
}

// The method that implements the
// delegated functionality
public void TimeHasChanged(
object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine("Current Time: {0}:{1}:{2}",
ti.hour.ToString(),
ti.minute.ToString(),
ti.second.ToString());
}
}

// A second subscriber whose job is to write to a file
public class LogClock
{
public void Subscribe(Clock theClock)
{
theClock.SecondChange +=
new Clock.SecondChangeHandler(WriteLogEntry);
}

// This method should write to a file
// we write to the console to see the effect
// this object keeps no state
public void WriteLogEntry(
object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine("Logging to file: {0}:{1}:{2}",
ti.hour.ToString(),
ti.minute.ToString(),
ti.second.ToString());
}
}

/* ======================= Test Application =============================== */

// Test Application which implements the
// Clock Notifier - Subscriber Sample
public class Test
{
public static void Main()
{
// Create a new clock
Clock theClock = new Clock();

// Create the display and tell it to
// subscribe to the clock just created
DisplayClock dc = new DisplayClock();
dc.Subscribe(theClock);

// Create a Log object and tell it
// to subscribe to the clock
LogClock lc = new LogClock();
lc.Subscribe(theClock);

// Get the clock started
theClock.Run();
}
}
}

没有评论:

发表评论