代码改变世界

Event design pattern

2011-12-27 10:19  barbarossia  阅读(184)  评论(0编辑  收藏  举报

Events are the most commonly used form of callbacks (constructs that allow framework to call into user code). Other callback mechanisms include members taking delegates, virtual members, and interface-based plug-ins. Data from usability studies indicates that the majority of developers are more comfortable with using events than with the other callback mechanisms. Events are nicely integrated with Visual Studio and many languages.

Under the covers, events are not much more than a field whose type is a delegate plus two methods to manipulate the field. Delegates used by events have special signatures (by convention) and are referred to as event handlers.

When users subscribe to an event, they provide an instance of the event handler bound to a method that will be called when the event is raised. The method provided by the user is referred to as an event handling method.

The event handling method’s signature is determined by the event handler. By convention, the return type of the method is void and it takes two parameters. The first parameter represents the object that raised the event. The second parameter represents event-related data that the object raising the event wants to pass to the event handling method. The data are often referred to as event arguments.

It is also important to note that there are two groups of events. Events raised before a state of the system changes, called pre-events, and events raised after a state changes, called post-events. An example of a pre-event would be Form.Closing event which is raised before a form is closed. An example of a post-event would be Form.Closed, which is raised after a form is closed. The following sample shows an AlarmClock class defining an AlarmRaised post-event.

The sample code is:

public class AlarmClock {
public AlarmClock() {
timer.Elapsed += new ElapsedEventHandler(TimerElapsed);
}

public event EventHandler<AlarmRaisedEventArgs> AlarmRaised;

public DateTime AlarmTime {
get { return alarmTime; }
set {
if (alarmTime != value) {
timer.Enabled = false;
alarmTime = value;
TimeSpan delay = alarmTime - DateTime.Now;
timer.Interval = delay.TotalMilliseconds;
timer.Enabled = true;
}
}
}

protected virtual void OnAlarmRaised(AlarmRaisedEventArgs e){
EventHandler<AlarmRaisedEventArgs> handler = AlarmRaised;
if (handler != null) {
handler(this, e);
}
}

private void TimerElapsed(object sender, ElapsedEventArgs e){
OnAlarmRaised(AlarmRaisedEventArgs.Empty);
}
private Timer timer = new Timer();
private DateTime alarmTime;
}
public class AlarmRaisedEventArgs : EventArgs {
new internal static readonly
AlarmRaisedEventArgs Empty = new AlarmRaisedEventArgs();
}

 It's copy from the <.Net Framework Design Pattern>