120 likes | 243 Views
Programming in C# Events. CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis. The event field. An event field is just a special delegate instance. Usually exposed as a public field (acts more like a property).
E N D
Programming in C#Events CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis
The event field • An event field is just a special delegate instance. • Usually exposed as a public field (acts more like a property). • Restricts the delegate operations (to the public) to += and -=. • Only the class (or its decendents) can fire the event. • Only the class (or its descendents) can clear or reset the values (using =).
Published Properties publicclassSharedFloat { publicdelegatevoidNewValue(float value); publiceventNewValue ValueChanging; publiceventNewValue ValueChanged; privatevoid Dummy(float value) {} public SharedFloat() { // This avoids the check for null. ValueChanging += Dummy; ValueChanged += Dummy; } } privatefloat myFloat; publicfloat Value { get { return myFloat; } set { ValueChanging(value); myFloat = value; ValueChanged(myFloat); } }
Example class Model { public eventNotifier notifyViews; public void Change() { ... notifyViews("Model"); } } class View { public View(Model m) { m.notifyViews += new Notifier(Update); } void Update(string sender) { Console.WriteLine(sender + " was changed"); } } class Test { static void Main() { Model model = new Model(); new View(model); new View(model); ... model.Change(); } }
Event Accessors • Event subscription can be controlled/monitored within a class. • Similar to properties – add accessor is called during +=, remove accessor is called during -= • Both accessors need to be declared. public delegate void MyDelegate (); class A { private MyDelegate m_DelegateBehind; public event MyDelegate Event { add { m_DelegateBehind += value; } remove { m_DelegateBehind -= value; } } … }
Classes with events • A class instance may publish several events. • Each event member holds a collection of subscribers. • As with delegates, the publishing object calls each registered listener in turn. .
Naming Conventions in .NET • The name of an event ends with ing if the notification occurs before the state change or actual event. • The name of an event ends with ed if the notification occurs after the state change or actual event. • Some typical event names • form.Closing// has not closed yet, this can abort the close • form.Closed// by this time the form is closed. • msg.Sending// suggests you can intercept and modify// the message just before sending • msg.Sent// telling you that it has already gone.
What does this buy us? • Flexible, loose coupling • Very clean separation of concerns • Easily extensible: we can add new observers without having to modify the publisher. • Modules can be “wired” to listen to one another as part of the startup logic, • The only type coupling between the modules is determined by the type of the event delegate.
Examples in .NET Framework • A Timer has a Tick event that you subscribe to. You can set the Interval between ticks. • The EventLog component allows you to listen to EventWritten, which will alert you every time anything is written to your machine’s event log. • The FileSystemWatcher component watches a directory structure. It uses a filter (e.g., “*.xml”) and exposes several events: • Changed • Created • Renamed • Deleted
The Event Pattern in .NET • Delegates for event handling in .NET have the following signature: delegate void SomeEvent (object sender, MyEventArgs e); • The return type is void. • The first parameter is a reference to the class that contains the event (the publisher). • The second parameter is used to pass (push) data to the subscribers. It’s type is derived from System.EventArgs. • Using this pattern, I can use a method like the following for all .NET events (using contra-variance): private void MyEventHandler( object sender, EventArgs e) { // log the event … } This method takes any object as the first parameter and any object derived from EventsArgs as the second.
Example public delegate void KeyEventHandler (object sender, KeyEventArgs e); public class KeyEventArgs : EventArgs { public virtual bool Alt { get {...} } // true if Alt key was pressed public virtual bool Shift { get {...} } // true if Shift key was pressed public bool Control { get {...} } // true if Ctrl key was pressed public bool Handled { get{...} set {...} } // indicates if event was already handled publicint KeyValue { get {...} } // the typed keyboard code ... } classMyKeyListener { public MyKeyListener(...) { keySource.KeyDown += new KeyEventHandler(HandleKey);} void HandleKey (object sender, KeyEventArgs e) {...} }
Programming in C#Events CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis