C#
  Home arrow C# arrow Creating Custom Delegates and Events in C#
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C#

Creating Custom Delegates and Events in C#
By: Joe E. Bennett
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 61
    2003-05-05

    Table of Contents:

    Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Joe has written an article for C# programmers wishing to create their own delegates and events in their C# applications with ease.

    Controls used on your forms have events associated with them you can respond to with event handlers in your application.  C# makes it easy to have the same behavior in other parts of your application by creating your own delegates and events, and raising the events based on your program logic. 

    There are three pieces that are related and must be included to make our custom events work.  They are a delegate, an event, and one or more event handlers.  In this article we will examine delegates and events, how they relate, and how to use them to create custom event handling for your applications.  The code to implement the delegates and events is also shown.  Details about the code are included in comments.

    Delegates

    A delegate is a class that can contain a reference to an event handler function that matches the delegate signature.  It provides the object oriented and type-safe functionality of a function pointer.  The .NET runtime environment implements the delegate; all you need to do is declare one with the desired signature.  It is customary for delegates to have two arguments, an object type named sender and an EventArgs type named e. 

    When you double click on a control in the forms designer of Visual Studio.NET, you are provided with a stub for an event handler that matches this signature.  This signature is not required and you may want a different signature for your custom events.  When a delegate is created and added to an event invocation list, the event handler is called when the event is raised.  Multiple delegates can be added to a single event invocation list and will be called in the order they were added. 

    Events

    Events are notifications, or messages, from one part of an application to another that something interesting has happened.  When an event is raised, all the delegates in the invocation list are invoked in the order they were added.  Each delegate contains a reference to an event handler, and each event handler executed.  The sender of the event does not know which part of the application will handle the event, or even if it will be handled. 

    It just sends the notification and is finished with its responsibilities.  It is often necessary to provide some information about the event when the notification is sent.  This information is normally included in the EventArgs argument to the event handler.  You will probably want to develop a class derived from EventArgs to send information for custom events.

    Suppose you are creating an application for a bank to manage accounts and want to raise an event when a transaction would cause the balance falls below some minimum balance.  There is no button to click when this happens, and you would not want to depend on a person noticing the balance is low and performing some action to indicate the balance is low to the rest of the application. 

    A low balance happens because of a withdrawal of some amount that reduces the account balance below the minimum required balance.  You want the notification to be automatic, so appropriate action can be taken by some other part of the application without user intervention.  This is where custom delegates and events are useful.  The C# code below will demonstrate how to use delegates and events for this example.

    First, create a class for our event arguments that is derived from EventArgs.  We will include properties for the account number, current balance, required minimum balance, a message describing the event, and a transaction ID.  You can include any information that would be useful for you application.

    public class AccountBalanceEventArgs : EventArgs
    {
     private string acctnum;
     public string AccountNumber
     {
      get
      {
       return acctnum;
      }
     }
     private decimal balance;
     public decimal AccountBalance
     {
      get
      {
       return balance;
      }
     }
     private decimal minbal;
     public decimal MinimumBalance
     {
      get
      {
       return minbal;
      }
     }
     private string msg;
     public string Message
     {
      get
      {
       return msg;
      }
     }
     private int transID;
     public int TransactionID
     {
      get
      {
       return transID;
      }
     }
     // AccountBalanceEventArgs constructor
     public AccountBalanceEventArgs(string AcctNum, decimal CurrentBalance,
      decimal RequiredBalance, string MessageText, int transactionID)
     {
      acctnum = AcctNum;
      balance = CurrentBalance;
      minbal = RequiredBalance;
      msg = MessageText;
      transID = transactionID;
     }
    }

    Now create the delegate.  Our delegate will have a return type of void and take an instance of our AccountBalanceEventArgs class as  the only argument.  The delegate does not have to be declared inside a class.  All our event handlers will have the same signature as this delegate.  In other words, they will return void and take a single AccountBalanceEventArgs argument.

    public delegate void AccountBalanceDelegate(AccountBalanceEventArgs);

    Our next task is to create a class containing one or more methods that will raise the event if the correct conditions exist in the application logic.  In this example, an instance of Account will raise the AccountBalanceLow event when a transaction, if completed, would cause the current balance of the account to fall below the required minimum balance.  The event is included in the class.

    public class Account
    {
     // Create an event for the Account class
     // It has the form public event delegateName eventName
     public event AccountBalanceDelegate AccountBalanceLow;
     private string acctnum;
     private decimal balance;
     private decimal minBalance;
     // This method could cause the balance to fall below the required minimum.
     // We will raise the event if the balance is not high enough to withdraw
     // amount without falling below the required minimum balance.
     // transID is some extra information about which transaction caused
     // the event to be raised, so it will be included in the event arguments.
     public void Withdraw(decimal amount, int transID)
     {
      // if the transaction would reduce the balance below the minimum,
      // raise the event
      if ((balance - amount) < minBalance)
      {
       DispatchAccountBalanceLowEvent(transID);
      }
      else
      {
       // everything is ok, so reduce the balance and no event is raised
       balance -= amount;
      }
     }
     // This method adds an event handler (delegate) to the event invocation list.
    // Any method that returns void and takes a single AccountBalanceEventArgs
    // argument can subscribe to this event and receive notification messages about an
    // AccountBalanceLow event.
     public void SubscribeAccountBalanceLowEvent(AccountBalanceDelegate eventHandler)
     {
      AccountBalanceLow += eventHandler;
     }
     // This method removes an event handler (delegate) from the event invocation list.
     // Any method that has already subscribed to the event can unsubscribe.
     public void UnsubscribeAccountBalanceLowEvent(AccountBalanceDelegate eventHandler)
     {
      AccountBalanceLow -= eventHandler;
     }
     // This method raises the event, which causes all the delegates in the event
     // invocation list to execute their event handlers.  The event handlers are executed
     // in the order the delegates were added.
     private void DispatchAccountBalanceLowEvent(int transaction)
     {
      // make sure the are some delegates in the invocation list
      if (AccountBalanceLow != null)
      {
       AccountBalanceLow(new AccountBalanceEventArgs(
        acctnum, balance, minBalance,
        "Withdrawal Failed: Account balance would be below minimum required",
        transaction));
      }
     }
     // the rest of the Account class implementation is omitted
    }

    Our final piece is to create a class with methods to handle the events.  Name it whatever is meaningful for your application.  Remember, the methods that will be event handlers for our event must have a signature that matches the delegate.

    public class EventHandlerClass
    {
     // This method will be an event handler.  It can be named anything you want,
     // but it must have the same signature as the delegate AccountBalanceDelegate
     // declared above.
     public void HandleAccountLowEvent(AccountBalanceEventArgs e)
     {
      // do something useful here
      // e.AccountNumber, e.AccountBalance, e.MinimumBalance,
      // e.Message, and e.TransactionID are all available to use
     } 
     // This method will be another event handler.  It can be named anything you
     // want, but it must have the same signature as the delegate
     // AccountBalanceDelegate declared above.
     public void HandleAccountLowEvent2(AccountBalanceEventArgs e)
     {
      // do something useful here
      // e.AccountNumber, e.AccountBalance, e.MinimumBalance,
      // e.Message, and e.TransactionID are all available to use
     }
     // the rest of the EventHandlerClass class implementation is omitted.
    }

    We now have all the code necessary to implement our custom event and have it handled by our event handlers.  All we need is to tie everything together.  Somewhere in your code, where it makes sense for your application, you would create instances of Account and EventHandlerClass, subscribe to the event notification, make a withdrawal and do something useful if the event is received.

    // somewhere in your code create instances of the Account class
    // and the EventHandlerClass class...
    EventHandlerClass handler = new EventHandlerClass();
    Account acct = new Account();
    acct.SubscribeAccountBalanceLowEvent(
     new AccountBalanceDelegate(handler.HandleAccountLowEvent));
    acct.SubscribeAccountBalanceLowEvent(
     new AccountBalanceDelegate(handler.HandleAccountLowEvent2));
    // if the next line causes the current balance to fall below the mimimum
    // balance, the event will be raised and handler.HandleAccountLowEvent will be
    // called followed by handler.HandleAccountLowEvent2
    acct.Withdraw(1000.00M, 1);
    acct.UnsubscribeAccountBalanceLowEvent(
     new AccountBalanceDelegate(handler.HandleAccountLowEvent2));
    // now only handler.HandleAccountLowEvent will be called if the event is raised
    acct.Withdraw(1000.00M, 2);
    acct.UnsubscribeAccountBalanceLowEvent(
     new AccountBalanceDelegate(handler.HandleAccountLowEvent));
    // now no event handlers will be called
    acct.Withdraw(1000.00M, 3);

    If we needed to add another event to our code, most of the work is already finished.  For example, if we wanted to add an AccountBalanceHigh event, we could use the same delegate and AccountBalanceEventArgs class. 

    We would need to declare the AccountBalanceHigh event, add the appropriate subscribe, unsubscribe and dispatch methods, create the event handlers, and raise the event when the balance for an account gets too high.  If you look back over the code you can see it would take more time to implement the event handlers than to add the new event.

    It is not difficult to implement our own delegates and events that allow us to send a notification that something interesting has happened from one part of our application to another.  C# provides all the necessary tools to include this capability with a minimum of effort.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

    More C# Articles
    More By Joe E. Bennett

     

    IBM® developerWorks developerWorks - FREE Tools!


    Check out the new Jazz space on developerWorks

    <a href="http://zeus.developershed.com/shonuff.php?blackbird=3853&zoneid=442&source=&dest=http%3A%2F%2Fwww.ibm.com%2Fdeveloperworks%2Fspaces%2Fjazz%3FS_TACT%3D105AGY31%26S_CMP%3DDEVSHED&ismap="><img src="http://images.devshed.com/corp/img/news/jazz01.gif" alt="developerWorks Jazz space" align="left"></a>You've heard the buzz about Jazz... want to know more about it from a developer's perspective? Check out the Jazz space on developerWorks. This space is an up-to-date resource for developers, including technical information about Jazz and products built on Jazz, like Rational Team Concert Express. The Jazz space includes content from a wide variety of sources, including links, feeds, and comments from experts.
    FREE! Go There Now!


    NEW! Achieving True Agility -- How process can change the behavior of your tools

    Achieving true agility is a never-ending effort. We will showcase how you can become agile incrementally, a few practices at the time.Which practices should any agile team strive to adopt? What additional practices should you consider based on your needs to scale? Adopting practices are however made much easier with the right tool support. What about if your tools adapt to your practices? We will take a look at how the Jazz technology can be leveraged to make your process change the behavior of your tools.
    FREE! Go There Now!


    NEW! Hello World: Monitor a simple business process using WebSphere Business Monitor V6.0.2

    This tutorial shows new users of IBM WebSphere Business Monitor Version 6.0.2 how to perform the "Hello World" equivalent for monitoring business process applications. It is intended to help you get familiar with the capabilities of the product.
    FREE! Go There Now!


    NEW! Krugle, developerWorks, and code search

    Ken Krugler, co-founder of code search company Krugle, and Laura Merling, vice president of Marketing and Business Development for Krugle, join to talk about the ins and outs of code search and what it means as a new feature for developerWorks users.
    FREE! Go There Now!


    NEW! Rational Talks to You: Grady Booch on Architecture

    Join this Rational Talks to You teleconference on November 29 at 1:00 pm ET to participate in an interactive discusssion with Grady Booch around architecture and reuse. Get your questions answered!
    FREE! Go There Now!


    NEW! Rational Talks to You: Scott Ambler on being agile in a global development environment

    Join this Rational Talks to You teleconference on December 6 at 1:00 pm ET to participate in an agile application development discussion and get your questions answered on using IBM Rational Method Composer in a distributed environment.Get your questions answered!
    FREE! Go There Now!


    NEW! Section 508 of the U.S. Rehabilitation Act: Web accessibility compliance

    Because access to government information continues to be an area of concern for many U.S. citizens with disabilities, the U.S. government enacted Section 508 of the Rehabilitation Act in 2001 to ensure that government agencies create accessible Web content, enabling all citizens to access the information they need. A fully accessible Web site makes Web content accessible to all individuals, including those with disabilities, who may be accessing Web content via a variety of user agents. Common user agents include standard Web browsers, text-only browsers, assistive devices and mobile devices such as cell phones or personal digital assistants (PDAs).
    FREE! Go There Now!


    NEW! Software Change and Configuration Management Solution Guidelines

    This whitepaper provides areas to consider when evaluating any software configuration management solution. It addresses how the IBM solutions (Rational ClearCase and Rational ClearQuest) meet the needs and requirements of both project leaders and developers to provide successful Software Change and Configuration Management.
    FREE! Go There Now!


    NEW! Trial download: IBM Rational Method Composer V7.2

    Get a free trial download of the latest version of IBM Rational Method Composer V7.2 which helps you deliver customized yet consistent process guidance to your project teams and IT organization, and includes the latest version of IBM Rational Unified Process (RUP), which has provided process guidance to teams since 1996.
    FREE! Go There Now!


    Refresh! IBM Rational Systems Development Solution eKit

    With IBM Rational Systems Development Solution, you can deliver products faster with higher quality. Within this kit, Read the “Model Driven Systems Development” white paper to see how to improve product quality and communication. Then check out the rest of the e-Kit to learn more about important topics that can affect the success of any software project through customer examples, tutorials, informative Webcasts, and best practices for designing, building and managing systems. From start to finish, at every stage in your projects, Rational Systems Development Solution can help your company reach its full potential.
    FREE! Go There Now!



    All FREE IBM® developerWorks Tools!

    C# ARTICLES

    - Introduction to Objects and Classes in C#, P...
    - Visual C#.NET, Part 1: Introduction to Progr...
    - C# - An Introduction
    - Hotmail Exposed: Access Hotmail using C#
    - Razor Sharp C#
    - Introduction to Objects and Classes in C#
    - Making Your Code CLS Compliant
    - Programming with MySQL and .NET Technologies
    - Socket Programming in C# - Part II
    - Socket Programming in C# - Part I
    - Creational Patterns in C#
    - Type Conversions
    - Creating Custom Delegates and Events in C#
    - Inheritance and Polymorphism
    - Understanding Properties in C#







    © 2003-2010 by Developer Shed. All rights reserved. DS Cluster 10 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek