Best Practices of Interface, Delegate and Events in .NET

No.of Views1559
Bookmarked0 times
Downloads 
Votes0
By  abhi2434   On  21 Feb 2011 19:02:03
Tag : .NET Frameworks , General
Inversion of control is an architectural design principle which modifies the general flow of control of a program. You can say a program is a sequence of instructions that are running in a predefined sequence. Hence the sequence of execution of the program representing a sub-routine is defined when the class is actually implemented. Therefore, when the object is produced, it would have a sequence of instruction through which the control moves when it is called to execute
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

Inversion of control is an architectural design principle which modifies the general flow of control of a program. You can say a program is a sequence of instructions that are running in a predefined sequence. Hence the sequence of execution of the program representing a sub-routine is defined when the class is actually implemented. Therefore, when the object is produced, it would have a sequence of instruction through which the control moves when it is called to execute.

Inversion of control is a special circumstance where you will invert the predefined control flow to some arbitrary call defined way down the stream by the user who actually using the component. In this post, I will show you how you can implement inversion of control in your code and also approaches which help you while implementing your own class.

You can generally implement inversion of control in C# using 3 approaches :

1. Interface
2. Delegate
3. Event

Interface

Interface is the nicest concept for any modern programming. Most of us love to write interfaces while declaring our own types. There are a lots of interesting benefits of writing an interface. Some of them only deals with more structured code design, while others allows you a strict way of communication between objects. Interface plays an important role when you need inversion of control. Let me put forward a sample code to deal with inversion of control :

public interface ICaller
{
        void InvertedMember1();
        void InvertedMember2();
}
public class MyCustomClass
{
        public ICaller Caller { get; set; }

        //actual implementation

        public MyCustomClass(ICaller caller)
        {
            this.Caller = caller;
        }

        public void MyMethod()
        {
            Console.WriteLine("Start of method Body");

            Console.WriteLine("Let me call the first member of the caller :");

            this.Caller.InvertedMember1();

            Console.WriteLine("subroutine ends... now in MyMethod again");

            Console.WriteLine("hmm.. Now its time to call another method");

            this.Caller.InvertedMember2();

            Console.WriteLine("Back go MyMethod. Its time to bid you bye bye");

            Console.ReadLine();
        }
 }

Say you have a class with a method which implements the inversion of control. In my code MyCustomClass requires to run some arbitrary method which the user of this class will provide later after the class is actually released to invert its control. For such reason, I have used an interface ICaller. The ICaller lets the class to call the method without actually implementing the code before calling the environment. The constructor ensures that when the object of the class is created it needs an implementation of the object.

Note : You should always check if Caller is Null before calling its member. I removed it from the code just to make it simple.

public class CallerImplemented : ICaller
    {
        #region ICaller Members

        public void InvertedMember1()
        {
            Console.WriteLine("Oh I dont know when actually the call to InvertedMember1 occurred");
        }

        public void InvertedMember2()
        {
            Console.WriteLine("Oh I dont know when actually the call to InvertedMember2 occurred");
        }

        #endregion
    }

Now during the runtime of the project, when the object of MyCustomClass is created, I need an implementation of ICaller. Hence I write my own code within the implementation, and the library (or MyCustomClass) will invert the control to me while it is executing the method MyMethod.

Image Loading

For public API, it is very useful to have public interfaces so that user code can be hooked easily with the existing API. There are lots of Interfaces available with .NET which lets you hook your own code into their predefined API.

Pros & Cons

  • Very strict implementation required. You need to explicitly expose a Type to the API you are using.
  • Implementation of all the method is required even though you don’t want to invert your control for some other methods. In our case if we do not want to invert my control for InvertedMember2, I cannot do it.

Delegate

Delegates are another important feature which promotes inversion of control. Delegates are special type which lets you wrap the reference of a method, and work just as an object. Hence when required, you can send your own method to the library and allow the library to call them, when required.

Delegate work great in C# as you have the option to send even anonymous delegates (which eventually a normal method in MSIL) and does not require to maintain a strong type declaration for a single method interface. Let us look at the code to see how we can use delegates to implement the same code :

public delegate void MyCustomDelegate();
    public class MyCustomClass
    {

        public MyCustomDelegate InvertedMember1 { get; set; }
        public MyCustomDelegate InvertedMember2 { get; set; }

        //actual implementation

        public MyCustomClass(MyCustomDelegate method1, MyCustomDelegate method2)
        {
            this.InvertedMember1 = method1;
            this.InvertedMember2 = method2;
        }

        public void MyMethod()
        {
            Console.WriteLine("Start of method Body");

            Console.WriteLine("Let me call the first member of the caller :");

            this.InvertedMember1();

            Console.WriteLine("subroutine ends... now in MyMethod again");

            Console.WriteLine("hmm.. Now its time to call another method");

            this.InvertedMember2();

            Console.WriteLine("Back go MyMethod. Its time to bid you bye bye");

            Console.ReadLine();
        }

    }

So almost the same code, with the use of delegate. We defined a public delegate type which can point to a method void(void) type. The properties are the actual objects which might get you a member which is sent from the client. Therefore the method which the client puts while creating object of this class will be called automatically when MyMethod is called.

Note : You should check if InvertedMember property is null before calling them in actual code. I intentionally removed it.

Now the call would look like :

MyCustomDelegate method1 = delegate()
  {
         Console.WriteLine("Oh I dont know when actually the call to InvertedMember1 occurred");
  };
  MyCustomDelegate method2 = () =>
  {
          Console.WriteLine("Oh I dont know when actually the call to InvertedMember2 occurred");
  };
  MyCustomClass cobj = new MyCustomClass(method1, method2);
  cobj.MyMethod();

Hence you can see, I have created two objects of MyCustomDelegate and assigned an anonymous delegate to it. I have used different syntax to make you clear that both represent the same thing.

Image Loading

You should note that I can even use normal method to associate with a delegate, just like anonymous methods.

Pros and Cons

  • Delegates are superior in the sense, it allows us to remove the maintenance of unnecessary types, even though they produce strong type in IL, and make our code cleaner.
  • You can make use of Action, Func generic delegates already present in the API, and hence remove unnecessary delegate declaration as well. I could have changed MyCustomDelegate with Action, and my code would work as it is.
  • Very useful when you want a short callback to execute.

Events

Finally, another option and somewhat the best approach for callbacks, is the use of events. Events acts as a notification from a type. You can subscribe a method (or even more than one method) to a type to ensure that the method will be called whenever the class thinks to call.

Event system allows you to totally decouple the notification system with that of the actual type. Hence it also ensures that the object will invert its control only when there is active subscription available. Now let us change the code a little so that it works with events.

public class MyCustomClass
    {

        private event Action _invertedMember1;
        public event Action InvertedMember1
        {
            add { this._invertedMember1 += value; }
            remove { this._invertedMember1 -= value; }
        }
        public virtual void OnInvertedMember1()
        {
            if (this._invertedMember1 != null)
                this._invertedMember1();
        }
        private event Action _invertedMember2;
        public event Action InvertedMember2
        {
            add { this._invertedMember2 += value; }
            remove { this._invertedMember2 -= value; }
        }
        public virtual void OnInvertedMember2()
        {
            if (this._invertedMember2 != null)
                this._invertedMember2();
        }
        

        //actual implementation

        public MyCustomClass()
        {
        }

        public void MyMethod()
        {
            Console.WriteLine("Start of method Body");

            Console.WriteLine("Let me call the first member of the caller :");

            this.OnInvertedMember1();

            Console.WriteLine("subroutine ends... now in MyMethod again");

            Console.WriteLine("hmm.. Now its time to call another method");

            this.OnInvertedMember2();

            Console.WriteLine("Back go MyMethod. Its time to bid you bye bye");

            Console.ReadLine();
        }

    }

You can see there is an event accessor defined for the events InvertedMember# which will let the subscription to work from outside to the actual event. The virtual OnInvertedMember# is just to check whether there is some active event or not. Null specifies there is no active subscription for the event.

From the method body, we call this virtual method to ensure that the event handlers (the method that we pass from outside for notification) will be called only when there is any active handler ready.

MyCustomClass cobj = new MyCustomClass();

cobj.InvertedMember1 +=  delegate()
{
      Console.WriteLine("Oh I dont know when actually the call to InvertedMember1 occurred");
};
cobj.InvertedMember2 += InvertedMember2;

cobj.MyMethod();


static void InvertedMember2()
        {
            Console.WriteLine("Oh I dont know when actually the call to InvertedMember2 occurred");
        }

Here, we separate the creation of the object with the event system. If we run without any active subscription, and call the MyMethod, it will write all the lines as it is. Once we subscribe, as in above, it will be called automatically by the event system. You can see the same output from it

Image Loading

I have intentionally showed that event system can also be activated with normal method just like anonymous method.

.NET actually uses Delegate.Combine feature (MultiCastDelegate) to hold the method as you pass and invokes Delegate.Remove when you unsubscribe the event. So if you pass more than one method for the same event, both of them will be called when the event is raised.

cobj.InvertedMember1 +=  delegate()
            {
                Console.WriteLine("Oh I dont know when actually the call to InvertedMember1 occurred");
            };
            cobj.InvertedMember1 += () => 
            {
                Console.WriteLine("Hey hey, this is another method..... ");
            };
            cobj.InvertedMember2 += InvertedMember2;

            cobj.MyMethod();

Thus the code above will produce output like this:

Image Loading

The line Hey hey, this is another method …. Is called automatically when event is raised.

Download Sample Project

Download source files -38 kb

Conclusion

As you understand each of the bits, it is now good to tell you that each of these way of invert your control has its own pros and cons. There are certain cases where you want Interfaces, while other might require the use of events, it totally depends on your requirement and the one suits your problem. I hope you found fun reading the article, and hope to see some feedback.
Thank you for reading.

 
Sign Up to vote for this article
 
About Author
 
abhi2434
Occupation-Not Provided
Company-Not Provided
Member Type-Senior
Location-Not Provided
Joined date-22 Oct 2009
Home Page-Not Provided
Blog Page-Not Provided
 
 
Other popularSectionarticles
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top
</