C# Delegates

 

System Requirement:
Windows2000
Microsoft .NET Framework Beta 2
Internet Information Server (IIS 5.0)
Visual Studio 7.0 Beta 2

Programming Language:
C#

Purpose:
The purpose of this utility is to understand the following using .NET Framework:
-What are Delegates
-How to add COM object using Run time Interop services

What are Delegates?

We all are familiar with the functions. Weknow that they perform a predefined set of work and return resultsbased on arguments passed to them. For instances, a functionAddOper(a,b) adds two numbers a and b and return the sum of these twonumbers. Now think of writing a function which is versatile i.e. it iscapable of performing a wide variety of tasks. Say it is capable ofadding, subtracting and multiplying numbers.

One way of writing such a function would be topass the type of operation we want to perform as argument along withthe values on which we want to perform our operation.Example:AddOper(a,b,"add") for adding a and b. Inside the function wewill be using the Select Case or if else statements for choosing thetype of operation we want to perform. This approach is obviouslycomplex and restrictive.

We want a very flexible and generic solution.We want to write a generic function called by the Main Applicationwhich in turn calls the appropriate function i.e. we are looking forsomething like this.

pic1 C# Delegates

Now, the question is, is it possible to write such flexible Applications?

Yes, it is achievable if we pass a method to amethod. Like GenericFun(AddOper). However, C# does not recommend thisapproach because of type safety reasons. Rather, C# has introduced anew object called DELEGATE for this purpose.

Like Class type, we define Delegate type andthen create an instance of delegate to hold the details of a function,note that the instance only contains the details such as functionsignature and return type and not function body.

The syntax of declaring the delegate is as follows:

Public delegate int GenericFun(int a, int b);

Essentially, we are saying that delegate willaccept functions whose return type is integer and which takes twoarguments of type integers.

Now, lets say we want to work with addition function defines as follows:Private int AddOper(int a,int b){}

Now, lets create an instance of this delegate and pass our add function to it.GenericFun gfAdd=new GenericFun(AddOper);

So you see the constructor of a delegate takes the function name.

Now, lets see how we can pass this delegate toa generic function PrintResult which can operate on any two numbers andreturns an integer. Thus it can be used to print the result ofAddition, subtraction, multiplication or any type of procedure whichtakes two integers and returns an integer. Currently, lets see how wecan make PrintResult to add two numbers.

//Define two numbers we want to add
int No1=40;
int No2=60;

//now call generic function to add these numbers
PrintResult(gfAdd,No1,No2)

You will see 100 on the console.

Now we will see how PrintResult method is defined.
Private int PrintResult(GenericFun action,int a,int b){
int result=action(a,b);
console.WriteLine(result);
}

so did you notice the magic! Just create aninstance of delegate passing it the function you want to work with andthen call your generic function passing it the delegate and you aredone.

To repeat the same exercise with subtraction function, we will do as follows:GenericFun gfSub=new GenericFun(SubOper);
PrintResult(gfSub,No1,No2);
However,it is possible to define an array of delegates, rather then definingeach separate delegate. Thus we can also do the following:

GenericFun[] gf=new GenericFun(AddOper),
new GenericFun(SubOper),

Then to execute Subtract operation, use the following syntax:
PrintResult(gf[1],No1,No2)

OK, Let me walk you through an example whichuses Events, to see how delegates can be used with Events. Note thatEvents are a type of delegates.

To understand what delegates are and how theycan be used, lets start with a simple scenario. A bank has a callcenter, which receives ATM card disputes. After the disputes aresettled, the bank Rep sends the customer the outcome of the dispute inone of the following ways:
Email, if an email address is available by clicking SendEmail button.
Fax, if fax number is available by clicking SendFax button or
Letter, if email address or fax number is not available by clicking SendLetter button.

So we need three event handlers to handle one of the following events:
SendEmailEvent handler
SendFax Handler,
SendLetter handler.

We also need a Generic function that is called by the Main Application and which in turns calls appropriate Event Handler.

Lets start by writing three classes, whichwill be called Email, Fax and Letters respectively. Each class willhave its own methods of sending Information. Therefore, Email classwill have SendEmailMessage method, Letter will have SendLetter and Faxwill have SendFax methods for sending information.

Now, we need another class calledMessageWatcher, which is responsible for invoking the appropriate sendmethod based on user's selection

We will also desigb a form with three buttonseach for sending a particular type of message. Now when Rep clicks theSendEmailMessage button, an event is generated, MessageWatcherintercepts this event and calls the appropriate Event Handler. In thiscase the SendEmailMessage method of Email class. Lets see how this canbe done.

pic2 C# Delegates

The MessageWatcher class and the generic SendMessage function is shown below.

//define MessageWatcher class which will send the messages
public class MessageWatcher {

//define messenger delegate
public delegate void MessageHandler(object Sender, MessageInfo mi);

//define an event
public event MessageHandler OnMessageSendRequest;

//This function is reasponsible of sending the messages
public void SendMessage(MessageInfo mr) {
//make sure it is defined
if (OnMessageSendRequest !=null)
OnMessageSendRequest(this,mr);
}

Notice that OnMessageSendRequest(this,mr)function is taking two arguments and does not return anything. Compareit with the SendEmailMessage function as shown below.

public void SendEmailMessage(object Sender,MessageInfo ei){}

It is extremely important that the sign
atureof all the participating functions along with the generic functionshould have identical signature. Thus the signature of SendEmailMessageand OnMessageSendRequest(this,mr) should have matching arguments andreturn type.

OK, so now the question is, how doesMessageWatcher class determines that it has to invoke theSendEmailMessage handler?For this, first EmailClass needs to notify the Watcher class that itwill handle the SendEmail event and it does this in its constructor.The syntax is as follows:

public Email(MessageWatcher mw){

//store watcher reference
watcher=mw;

//tell MessageWatcher that it will handle the SendEmail event
watcher.OnMessageSendRequest+=new MessageWatcher.MessageHandler(SendEmailMessage);
}

When the Email class is instantiated, itnotifies the MessageWatcher that when OnMessageSendRequest event israised, it will handle the event.

Did you notice that MessageHandler is thedelegate and we are simply passing it the function nameSendEmailMessage. So the Email class is essentially notifying theMessageWatcher class that it will handle the SendEmailMessage event.

Finally, in the main application we use these three lines.
//create an instance of email class
MessageWatcher mw=new MessageWatcher();
Email em=new Email(mw);mw.SendMessage(mi);

When the Rep clicks the SendEmailMessagebutton, the Main Application create an instance of MessageWatcher classand Email class. The Email constructor is passed the instance ofwatcher class. When Email class is instantiated, it notifies theMessageWatcher instance that it will handle the event which in our caseis SendEmailMessage. Finally, the Main Application calls the genericSendMessage function of the MessageWatcher class passing it theMessageInfo data structure.

The SendMessage function MessageWatcher classraises OnMessageSendRequest(this,mr) event and since the Email classhas already notified the MessageWatcher class that it will handle theSendEmailMessage event therefore SendEmail function is called to handlethis event.

The Email class makes use of .NET System.Web classes for sending emails.

The Letter class makes use of Microsoft Wordlibrary. Since this library is a COM component thereforeI have used theSystem.Runtime.InteropServices. This class uses a template letter whichhas bookmarks for inserting texts for a customer.

Related Articles :

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!