Fernando Machado Píriz's Blog

Posts about digital transformation, enterprise architecture and related topics

Inversion of Control, Dependency Injection, and Managed Extensibility Framework

with 4 comments

Inversion of Control and Dependency Injection are a sort of buzz words, in the sense that when you dig into their definitions, they do not necessarily means exactly the same thing to different people. Recently I engaged in a discussion with my good friend Leon Welicki from Microsoft’s WF team, around the simple question is the Managed Extensibility Framework an Inversion of Control/Dependency Injection framework? I will try to answer this question. If you are new to MEF, you can read an introduction in this previous post.

The concept of Inversion of Control is not new. It comes from the old times when almost all object-oriented code was written in Smalltalk.

When describing desirable framework design characteristics, Ralph Johnson and Brian Foot wrote: “One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code. The framework often plays the role of the main program in coordinating and sequencing application activity. This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application” (JOOP, 1988).

Even before, while talking about design decisions for the user interface of a software development environment called Tajo, Richard Sweet coined the now famous Hollywood’s Law: “‘Don’t call us, we’ll call you’: A tool should arrange for Tajo to notify it when the user wishes to communicate some event to the tool, rather than adopt an ‘ask the user for a command and execute it’ model” (ACM SIGPLAN, 1985)

Inversion of Control is frequently associated with containers such as Spring.NET, Castle, etc. My assertion can be controversial, but for me inversion of control concept is independent of containers. Every time you have an object of class A calling methods of an object of class B to achieve some task, and you manage to have object B calling object A to do the same task, you are using Inversion of Control. Let me give you an example. If you have a window class instance (object A) and a set of controls contained in that window (objects B), the window can set control’s properties in a certain way to get a particular and consistent look and feel for all of his controls. Or you can manage to have the controls (objects B) asking for their properties to the window containing them (object A); as a result the look and feel can be exactly the same as before. In this simple case, you are doing inversion of control, without using any container at all.

But (there is always a but) if your application involves more classes and more scenarios than just a window configuring his controls’ properties, as usually happens, applying Inversion of Control is not an easy task. Challenges like finding, assembling, and containing instances of dependent objects (objects B) might be cumbersome. That is why we need containers like the aforementioned ones.

Furthermore, when applications start getting bigger and complex, so do dependencies between classes. One way to get dependencies under control is by using Dependency Injection, which allows you to declaratively inject objects (objects B) into another class instance (object A), rather than relying on the class instance creating the object itself. Containers designer knows this and framework design heavily uses it, so most Inversion of Control containers are implemented using Dependency Injection. By the way, Service Locator can be used instead of Dependency Injection to achieve similar results.

What all that stuff has to do with MEF? Let me better illustrate how you implement Inversion of Control/Dependency Injection by using MEF with the following example. I want to add to an existing application the ability to show an icon in the notification area of the taskbar when minimized.

clip_image001

You can add this feature by using a NotifyIcon class instance in your application’s main window. Basically, you will need to:

  • Create an instance of NotifyIcon class and setup some of its properties like the icon and the text.
  • Wire the Click event of the NotifyIcon instance to a method in the main window, so you can restore the main window when the user clicks the icon.
  • Show the NotifyIcon instance when main window’s state changes from normal to minimized, and vice versa. You will also need to hide the main window when it is minimized, and vice versa.

The code below does exactly those things:

public partial class MainWindow : Window
{
    Forms.NotifyIcon notifyIcon;

    // Creates the main window and the notify icon
    public MainWindow()
    {
        InitializeComponent();
        notifyIcon = new Forms.NotifyIcon();
        notifyIcon.Text = Title;
        notifyIcon.Icon = GetIcon();
        notifyIcon.Click += new EventHandler(NotifyIcon_Click);
    }

    public System.Windows.Forms.NotifyIcon NotifyIcon
    {
        get
        {
            throw new System.NotImplementedException();
        }
        set
        {
        }
    }

    // Gets an icon from the application icon resources.
    private Drawing.Icon GetIcon()
    {
        Drawing.Icon result = null;
        Assembly assembly = GetType().Assembly;
        Stream stream = assembly.GetManifestResourceStream("NotifyIconDemo.Presentation.ico");
        if (stream != null) result = new Drawing.Icon(stream);
        return result;
    }

    // Shows the form when the user clicks on the notify icon.
    private void NotifyIcon_Click(object sender, EventArgs e)
    {
        this.Show();
        this.WindowState = WindowState.Normal;
    }

    // Hides this window and shows the notify icon when minimized and vice versa when restored.
    private void Window_StateChanged(object sender, EventArgs e)
    {
        if (this.WindowState == WindowState.Minimized)
        {
            this.Hide();
            notifyIcon.Visible = true;
        }
        else
        {
            notifyIcon.Visible = false;
        }
    }
}

 You can download the full solution from here. The project with this code is NotifyIconDemo.1. In order to run this code directly form Visual Studio, you will need to choose this project as startup project, by selecting the Set as Startup Project in the project’s pop up menu.

A problem with this approach is the high coupling between MainWindow and NotifyIcon classes. Once you code a program like this, you will never be able to reuse the MainWindow class without using also the NotifyIcon class: there are calls to NotifyIcon’s methods in almost every MainWindow method. In addition, if there were other implementations of an icon in the notification area of the taskbar, you will never be able to use them without making some (or a lot of) changes. And last but not least, it is almost impossible to test NotifyIcon’s behavior separately from MainWindow’s behavior.

Let us solve this problem step by step. The code for this second version is also in the solution here.

First we need to create an interface to separate the type from its implementation:

public interface INotifyIcon
{
    Window MainWindow { get; set; }
    string Text { get; set; }
    Drawing.Icon Icon { get; set; }
}

 The project for the interface is NotifyIconDemo.2.Common. What properties do in this interface is pretty obvious, so for the sake of simplicity I will omit further comments.

Now we need a class implementing this interface. We can even implement this class in a different assembly, as soon as we add a reference to this new assembly in the main project. This new class should contain most of the logic to manage the NotifyIcon class and to respond to events, previously in the MainWindow:

public class NotifyIconImpl : INotifyIcon
{
    Forms.NotifyIcon notifyIcon;
    Window mainWindow;

    public string Text { get { return notifyIcon.Text; } set { notifyIcon.Text = value; } }

    public Drawing.Icon Icon { get { return notifyIcon.Icon; } set { notifyIcon.Icon = value; } }

    public Window MainWindow
    {
        get { return mainWindow; }
        set
        {
            mainWindow = value;
            mainWindow.StateChanged += new EventHandler(Window_StateChanged);
            Text = mainWindow.Title;
            Icon = GetIcon();
        }
    }

    // Gets an icon from the application icon resources.
    private Drawing.Icon GetIcon()
    {
        Drawing.Icon result = null;
        Assembly assembly = mainWindow.GetType().Assembly;
        Stream stream = assembly.GetManifestResourceStream("NotifyIconDemo.Presentation.ico");
        if (stream != null) result = new Drawing.Icon(stream);
        return result;
    }

    // Creates a new instance of the notify icon
    public NotifyIconImpl()
    {
        notifyIcon = new Forms.NotifyIcon();
        notifyIcon.Click += new EventHandler(NotifyIcon_Click);
    }

    // Shows the form when the user clicks on the notify icon.
    private void NotifyIcon_Click(object sender, EventArgs e)
    {
        mainWindow.Show();
        mainWindow.WindowState = WindowState.Normal;
    }

    // Hides this window and shows the notify icon when minimized and vice versa when restored.
    private void Window_StateChanged(object sender, EventArgs e)
    {
        if (mainWindow.WindowState == WindowState.Minimized)
        {
            mainWindow.Hide();
            notifyIcon.Visible = true;
        }
        else
        {
            notifyIcon.Visible = false;
        }
    }
}

The project for the class is NotifyIconDemo.2.NotifyIcon.

Notice first that the main window owning the notify icon is stored or retrieved via the MainWindow property. When MainWindow is assigned, an event handler for main window’s StateChanged event is wired. This way the NotifyIconImpl class can detect when the main windows is minimized or restored, and show or hide the NotifyIcon instance. This event handler is almost the same than in the previous version, but is now in the NotifyIconImpl class, instead of the MainWindow class.

Obviously, the event handler of the Click event in the MainWindow instance is wired to a method in the NotifyIconImpl. This method will restore the main window previously assigned via the MainWindow property.

If no main window is assigned, no icon will be shown, but this is okay. By the way, if no icon is assigned, the icon will not be shown either, but this is the default behavior of the NotifyIcon class.

Be aware that NotifyIconImpl class can be tested without referencing the main window. You will need a Window instance, of course, but any Window instance will do the work, not only an instance of our MainWindow class.

Now take a look on how simple the MainWindow class resulted after these changes:

public partial class MainWindow : Window
{
    // Creates the main window and the notify icon
    public MainWindow()
    {
        InitializeComponent();

        INotifyIcon notifyIcon = new Impl.NotifyIconImpl();
        notifyIcon.MainWindow = this;
    }
}

References to INotifyIcon and NotifyIconImpl are contained just into the constructor, and not widely spread as before.

Note that the control was inverted. Except for the creation and initialization of the instance of NotifyIconImpl, all method calls are from NotifyIconImpl class to MainWindow class.

This second version is much better than the first one, but still is not perfect. Even if in MainWindow’s constructor we declare notifyIcon instance variable as INotifyIcon, we cannot change NotifyIconImpl for another class implementing the same interface without changing the line that creates the instance. Here is when MEF comes to help.

We need to do just a couple of changes. First, we need to decorate our NotifyIconImpl class with the Export attribute:

[Export(typeof(INotifyIcon))]
public class NotifyIconImpl : INotifyIcon

Code for this third version is also available here. The project for this interface is NotifyIconDemo.3.NotifyIcon.

Then we declare a private INotifyIcon instance variable in the MainWindow class, and decorate it with the Import attribute:

[Import(typeof(INotifyIcon))]
INotifyIcon notifyIcon;

The project in the demo solution for this interface is NotifyIconDemo.3.Common.

MEF will look for a class implementing this interface, will create an instance, and assign it to the instance variable. For this to happen, the following lines of code need to be added to the constructor, right before setting notifyIcon properties:

DirectoryCatalog catalog = new DirectoryCatalog(".");
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);

if (notifyIcon != null)
{
    notifyIcon.MainWindow = this;
}

The dependency between MainWindow and NotifyIconImpl through the notifyIcon instance variable is injected when calling ComposeParts method of the CompositionContainer class.

With these changes, in addition to all the good things we already achieved in the previous versions, now we are completely independent of the NotifyIconImpl class. It’s not referenced at all from MainWindow class. The NotifyIcon’s assembly is not even in the list of references of MainWindow’s project.

In order to change INotifyIcon implementation, all we need to do is replace the assembly containing the NotifyIconImpl class for another assembly containing other class implementing that interface, and decorate that class with the Export attribute.

Hopefully, at the end of this somehow long post, you will be convinced of MEF being an Inversion of Control/Dependency Injection framework.

The code example is taken from a larger demonstration of MEF I will be posting about soon. Get ready.

Advertisements

Written by fernandomachadopiriz

May 7, 2010 at 4:32 pm

4 Responses

Subscribe to comments with RSS.

  1. […] application sample created in C# that I use when blogging about Managed Extensibility Framework, Dependency Injection and Inversion of Control, etc. It demonstrates how an extensible application can be built as a container of component […]

  2. […] creada en C# que uso como ejemplo en algunos artículos sobre Managed Extensibility Framework, Dependency Injection and Inversion of Control, etc. que escribo en este blog. Demuestra cómo construir una aplicación extensible formada por un […]

  3. This was a great example. I particularly liked the way that you presented the example with no MEF, redeveloped it so that it had IOC then finally added MEF to fully redevelop it – the 3 staged approach really demonstrates the full process well.

    David Ree

    June 7, 2010 at 6:07 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: