In This article we are going to discuss how we can use a
delegate in a real time application to build dynamic components.
Introduction
Below are two important features in delegate which helps to make a component dynamic.
1- 1. It allows to inject code by the client
2-
2. Multi-casting
Inject functions by client code.
One
important use of delegate is with the help of delegate we can develop a component which client can
use and inject their functionality to it. In the below example I have shown a
UserRegistration Component. Client will call this component to register a user
,however it entirely depends on the client to implement how they want to notify users
about their registration via email or via SMS .
namespace
RegistrationModule
{
public delegate void NotifyUser(ContactDetail
objContact);
class RegisterUser {
public void Register(Userinfo
objUser, NotifyUser myFunc) {
//code to
save the user details to the database
//
myFunc(objUser.objContact);
}
}
class Userinfo {
public string name; public int age; public ContactDetail objContact; }
class ContactDetail {
public string email; public string mobNo; }
}
Client Code:
Lets say first client wants to send SMS to notify their
user.So below will be their implementation.
I have given the comment to explain the code.
//Below function is having same signature as delegate NotifyUser and will be attached to the delegate.public void SendSMS(ContactDetail
objContact)
{
string
MobNo = objContact.mobNo; //Add
your code to send Registration success message to the user mobile number.
}
public void RegisterUser()
{ //Create an Object of Userifo and fill the user details to it. Userinfo
obj = new Userinfo();
obj.name = "Sathish";
obj.age = 27;
ContactDetail
objC = new ContactDetail();
objC.mobNo = "9999999999";
objC.email = "sathish.siri.1985@gmail.com";
obj.objContact = objC;
//Create a delegate instance and attach the SendSMS() to it. NotifyUser
sendSMS = new NotifyUser(SendSMS);
RegisterUser
objReg = new RegisterUser();
//Invoke the register function with the Delegate Instance sendSMS
objReg.Register(obj, sendSMS);
}
Now lets say the second client wants to notify the user via
email:
public void SendEmail(ContactDetail
objContact)
{ string strEmail = objContact. email;
//Add
your code to send Registration success email to the user email address.
}
public void RegisterUser()
{
Userinfo
obj = new Userinfo();
obj.name = "Sathish";
obj.age = 27;
ContactDetail
objC = new ContactDetail();
objC.mobNo = "9999999999";
objC.email = "sathish.siri.1985@gmail.com";
obj.objContact = objC;
NotifyUser
sendEmail = new NotifyUser(SendEmail);
RegisterUser
objReg = new RegisterUser();
objReg.Register(obj, sendEmail);
}
That's it.Now client-1 user will get
user registration success message as an SMS and client-2 will
get user registration success message as an email. Important thing to
notice here is SendSMS and SendEmail is
the code written by the client however it is invoked by the
RegistrationModule
what in other words we can say delegates allow us to inject
functionality.
usr.Notify += new NotifyUser(SendEmail);
multi-casting
In the above scenario let’s say the client wants to send the notification
both via email and SMS, well below is the simple change he has to make.
usr.Notify = new NotifyUser(SendSMS);
usr.Notify += new NotifyUser(SendEmail);
usr.Register();
What is
an Event?
Ø Event provides a way for objects to notify state change or any
action.
Ø Technically events are delegate instance declared with event
keyword.
Ex :
delegate void
Print();
event Print
OnStartPrint;
Why
Events? Can not delegate do the same thing?
Yes delegate can do the same
thing, but does not give abstraction. Means client can invoke the delegate
where ever they want ,but event won’t allow that.
Show me a
practical example showing difference between event and delegate?
Let’s
consider our above example of user registration.
class Program
{
static void Main(string[]
args)
{
User
usr = new User();
usr.Name = "sathish";
usr.Age = 27;
usr.Contact.Email = "sathish.siri.1985@gmail.com";
usr.Contact.MobNo = "9999999999";
usr.Notify = new NotifyUser(SendEmail);
usr.Register();
Console.Read();
}
static void SendEmail(ContactDetail
objContact, string NotificationMsg)
{
string
email = objContact.Email;
//Add
your code to send NotificationMsg to the user email.
Console.WriteLine("email Sent to" + email);
}
}
Looks good
with delegate , but what if the client
uses the below code.
class Program
{
static void Main(string[]
args)
{
User
usr = new User();
usr.Name = "sathish";
usr.Age = 27;
usr.Contact.Email = "sathish.siri.1985@gmail.com";
usr.Contact.MobNo = "9999999999";
usr.Notify = new NotifyUser(SendEmail);
usr.Notify(usr.Contact, "Your TPIN is 1234");
//usr.Register();
Console.Read();
}
static void SendEmail(ContactDetail
objContact, string NotificationMsg)
{
string
email = objContact.Email;
//Add
your code to send NotificationMsg to the user email.
Console.WriteLine("email Sent to" + email);
}
}
Output:
Now the SMS is sent even though the user is not registered.
So now a question, should we allow the client
to write the below line of code, ie should we give access to him to invoke the
delegate?
usr.Notify(usr.Contact, "Your TPIN is 1234");
Off course NO, in our case because only User.Register()
method knows when userid is created and
when password is created ,so no one other than User class should be allowed to
invoke the delegate.
So how do we fix this
problem...simple use event. By declaring the Notify as event user will get
compilation error if he attempts to invoke the event by below line
usr.Notify(usr.Contact, "Your TPIN is 1234");
So what changes we have
to make in our program?
1. Just
add the event keyword before the delegate name NotifyUser in the
RegistrationModule.User class as below.
public
event NotifyUser Notify;
2. Use += instead of = for
initializing events i.e