The sample presented here builds on the various pieces discussed in Events and Delegates, and Providing Event Functionality. It consists of the following classes:
AlarmEventArgs
defines the data for the alarm event. It is instantiated by the class that raises the event, which, in this example, is the Alarm
class.AlarmEventHandler
is the delegate for the alarm event.Alarm
is the component that raises the alarm event.WakeMeUp
is a class that has a method AlarmRang
that handles the alarm event.AlarmDriver
is a class that demonstrates how events are wired. It instantiates WakeMeUp
, and then creates a delegate that will allow WakeMeUp
to receive alarm events. The delegate is an instance of AlarmHandler
that has a reference to the AlarmRang
method of the WakeMeUp
instance in its constructor. AlarmDriver
completes the event wiring by registering the delegate with the instance of Alarm
, using the AddOnAlarm
method of Alarm
.
Note There is no class named AlarmEvent. The data for the alarm event is in AlarmEventArgs
.
To compile and run this sample
csc EventDelegate.cs
[C#] //EventDelegateSample.cs // namespace EventDelegateSample{ using System; using System.ComponentModel; // Class that contains the data for //the alarm event. Derives from System.EventArgs //public class AlarmEventArgs : EventArgs
{ private readonly bool snoozePressed ; private readonly int nrings; //constructor // public AlarmEventArgs(bool snoozePressed, int nrings) { this.snoozePressed = snoozePressed; this.nrings = nrings; } //The NumRings property that returns the number of rings //that the alarm clock has sounded when the alarm event //is generated. // public int NumRings{ get { return nrings;} } //The SnoozePressed property that indicates whether the snooze //button is pressed on the alarm when the alarm event is generated. // public bool SnoozePressed { get { return snoozePressed; } } //The AlarmText property that contains the wake-up message. public string AlarmText { get { if (snoozePressed) { return ("Wake Up!!! Snooze time is over."); } else { return ("Wake Up!"); } } } } // Delegate declaration //public delegate void AlarmEventHandler
(object sender, AlarmEventArgs e); // The Alarm class that raises the alarm event. // This class does not have to be a component. In this example it // is, becasue this discussion is in the component developer's guide. //public class Alarm : Component
{ private bool snoozePressed = false; private int nrings = 0; private bool stop = false; //The Stop property indicates whether the //alarm should be turned off. // public bool Stop { get { return stop; } set { stop = value; } } //The SnoozePressed property indicates whether the snooze //button is pressed on the alarm when the alarm event is generated. // public bool SnoozePressed { get { return snoozePressed; } set { snoozePressed = value; } } // the AlarmEventHandler member // private AlarmEventHandler alh = null; // AddOnAlarm is the event hook that enables clients to // attach event handlers. // The Combine method of the Delegate class adds a delegate // to the existing list of delegates. // public void AddOnAlarm(AlarmEventHandler handler) { alh = (AlarmEventHandler)Delegate.Combine(alh, handler); } // RemoveOnAlarm allows clients to remove event handlers. // The Remove method of the Delegate class removes a delegate from // the existing list of delegates. // public void RemoveOnAlarm(AlarmEventHandler handler) { alh = (AlarmEventHandler)Delegate.Remove(alh, handler); } // The protected OnAlarm method raises the event by invoking // the delegates. The sender is always "this", the current instance // of the class. // protected virtual void OnAlarm(AlarmEventArgs e) { if (alh != null) { alh(this, e);//Invokes the delegates. } } //This is a cheap alarm clock that does not have //a user interface. //To simulate the alarm mechanism it has a loop //that raises the alarm event at every iteration //with a time delay of 300 milliseconds, //if snooze is not pressed. If snooze is pressed //the time delay is 1000 milliseconds. // public void Start(){ for (;;) { nrings++; if (stop) { break; } else if (snoozePressed) { System.Threading.Thread.Sleep(1000); { AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings); OnAlarm(e); } } else { System.Threading.Thread.Sleep(300); AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings); OnAlarm(e); } } } } //The WakeMeUp class that has a method AlarmRang that handles the //alarm event. //public class WakeMeUp
{ public void AlarmRang(object sender, AlarmEventArgs e) { Console.WriteLine(e.AlarmText +"\n"); if (!(e.SnoozePressed)) { if (e.NumRings % 10 == 0) { Console.WriteLine(" Let alarm ring? Enter Y"); Console.WriteLine(" Press Snooze? Enter N"); Console.WriteLine(" Stop Alarm? Enter Q"); String input = Console.ReadLine(); if (input.Equals("Y") ||input.Equals("y")) return; else if (input.Equals("N") || input.Equals("n")) { ((Alarm)sender).SnoozePressed = true; return; } else { ((Alarm)sender).Stop = true; return; } } } else { Console.WriteLine(" Let alarm ring? Enter Y"); Console.WriteLine(" Stop Alarm? Enter Q"); String input = Console.ReadLine(); if (input.Equals("Y") || input.Equals("y")) return; else { ((Alarm)sender).Stop = true; return; } } } } //The driver class that hooks up the event handling method of //WakeMeUp to the alarm event of an Alarm object using a delegate. //In a Forms based application, the driver class is the //form. //public class AlarmDriver
{ public static void Main (string[] args) { //instantiates the event receiver WakeMeUp w= new WakeMeUp(); //Instantiates a delegate that holds a reference to //the AlarmRang method of the WakeMeUp instance. AlarmEventHandler alh = new AlarmEventHandler(w.AlarmRang); //Instantiates the event source. Alarm al = new Alarm(); //Registers the event handler with the event source so //that the WakeMeUp instance can receive alarm events. al.AddOnAlarm(alh); al.Start(); } } }