How to raise and consume custom events in C#
When something happens asynchronously, the events mechanisms in C# is a good way for different components of our C# programs to notify one another about it.
For example, when the report generation component had the finance report ready, it can raise an event to components that had registered interest in that finance report.
This post documents how we can raise and consume custom events in C#.
Defining a delegate for components that are interested in the event
We first define the delegate that will hold C# methods from components which need to be notified when our report is completed by the report generation module.
Components which are interested in the report generation module shall provide a method that returns nothing and accepts a string
as its only input parameter.
public delegate void ReportCompletedHandler(string report);
I tend to put the definition of the delegate in the same source file that defines the component which will fire the event.
Defining the event object
We then define the event object as an instance variable in the class definition of the component which will fire the event.
public event ReportCompletedHandler reportCompleted;
The event keyword defines the delegate that we had defined earlier as a custom event and makes the event available through the variable reportCompleted
.
Registering interest in the event
To register interest in the event, we first define a method which had the same signature as the delegate, ReportCompletedHandler
.
private void displayReport(string report) { Console.WriteLine("Received report: " + report); }
And then add the method as a delegate to the event:
reportCompleted += new ReportCompletedHandler(this.displayReport);
Firing the event
When the report is ready, the report generation component will first check whether there are delegates registered to the reportCompleted
event. If there are interested parties registered to the event, it will fire the event.
String report = "<A sample report>"; if (reportCompleted != null) { reportCompleted(report); }
A complete example for this post
The delegate and event generator source
// Define delegate for components that are interested in report completion public delegate void ReportCompletedHandler(string report); // The event generator source public class ReportGenerator { public event ReportCompletedHandler reportCompleted; public void generateReport() { // Fire report completed event with report string report = "<A sample report>"; if (reportCompleted != null) { reportCompleted(report); } } }
A component that is interested in report completion
public class ReportDisplayer { public ReportDisplayer() { // Register interest in the completed report ReportGenerator.getInstance().reportCompleted += new ReportCompletedHandler(this.displayReport); } public void displayReport(string report) { Console.WriteLine("Diplaying report:"); Console.WriteLine(report); } }
Class that contains the main method to start the program
using System; public class Program { public static void Main(string[] args) { // Set up report displayer ReportDisplayer reportDisplayer = new ReportDisplayer(); // Trigger report generation ReportGenerator.getInstance().generateReport(); } }