Pages

Sunday, February 20, 2011

Inversion of Control : Practical usage of Interface, Delegate or Events

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

Here I will implement each of them with sample code.

Download Sample Code : 39KB



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.



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.


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.



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:


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

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.

Download Sample Code : 39KB


I hope you found fun reading the article, and hope to see some feedback.
Thank you for reading.

8 comments:

  1. Nice post bro. lucky 2 learn alot from ur articles.

    Btw, is there no cons for delegates usage? Just a wired thought :)

    ReplyDelete
  2. Thank you very much for this post. I have read several articles about IOC in the past but astonishingly they all dealt with DI. I was always sceptical about that. Of course IOC uses DI in your first example pattern but generally DI has nothing to do with IOC.
    At last here is an article which clearly explains in simple code what IOC is all about.
    Thank you :-)

    ReplyDelete
  3. Hi,

    um, actually this is not inversion of control, as one class is still in control of when the methods or other classes get called, regardless of whether you are using an interface, events, or delegates.

    Inversion of Control means that a class gives up control to other components. They may call you, or fire a common event that you respond to. If one class is calling another class directly (even via an interface), it is in control.

    Phil

    ReplyDelete
  4. Getting to know IOC is like the search for the holy grail now. Why is everyboedy talking about IOC but means DI? Take all those DI/IOC framework for instance. All code samples I find just deal with dependency injection.
    @philxan (or anyone else): Could you please provide us a sample of real IOC?

    ReplyDelete
  5. @philxan

    Control Reference is kept from Entry point of a program to its end. So basically if you think of them, its basically impossible to invert control without reference of control being present in the other component.

    ReplyDelete
  6. Yeah it's me again. :)
    Sorry but this is a very interesting topic.
    I just had another look at your delegate sample. I recognize this structure as "callback". So does this mean that any callback is also IOC?

    ReplyDelete
  7. @Rainer Hilmer

    Yes, IOC is a broader concept while DI is a part of it. Yes, I used DI to explain IOC in this post, but there are quite some other options too to define IOC. IOC can also be implemented with respect to Plugins, where the Plugins are loaded dynamically and control is inverted at times within that plugin (which being an individual app instance).

    DI is a part of IOC.

    I am writing a new post on DI, and Unity Framework for IOC Containers. I will explain the difference there for you. Please stay tune.

    ReplyDelete
  8. @Rainer Hilmer

    Hmm, You can say so. Callback means Inverting your own flow of Control to your callback interface. Hence once the callback interface releases the control, you will find the control again back to your own component.

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.