Dependency Injection and MEF

Dependency Injection

Dependency injection is an architectural design pattern applied throughout the framework and highly encouraged in your own applications. The basic idea is to externalize dependencies between classes, so they can be controlled and resolved at a higher level. Let’s look at a common dependency scenario to illustrate the pattern.

public class A
{
    private B _objectB;

    public A()
    {
        _objectB = new B();
    }
}

public class B
{
}

In this illustration, class A uses class B. There’s nothing technically wrong with this approach. Let’s imagine for a second, though, that we want an A that works with a subclass of B, because we want to extend the out-of-the-box B implementation. Currently, we have no way of replacing B with a subclass. Even subclassing A isn’t going to help us here, because the dependency is private. The way out of this bind is to externalize the dependency.

public class A
{
    private B _objectB;

    public A(B objectB)
    {
        _objectB = objectB;
    }
}

public class B
{
}

With just a minor change, we can now supply B from the outside, whenever we create an A. The constructor takes an instance of B and injects it into the instance of A during creation. This is what dependency injection is all about. A simple yet powerful approach.

The Concept of Inversion of Control (IoC)

Hand in hand with dependency injection goes the concept of inversion of control. Without mentioning it, inversion of control is what we achieved in the above illustration. In the initial illustration, the control lies with A. A creates and controls B. In the second illustration, we inverted that control and now the control lies with the part of the application that creates an instance of A. It decides and controls which specific B is injected into A.

In a modern application, this control is typically delegated to an IoC container for ultimate flexibility and maintainability. An IoC container manages instances and resolves dependencies between them.

A objectA = container.CreateA();

The above snippet illustrates what we mean by that. Instead of A objectA = new A(new B()), we request an instance from our fictitious container. The idea is that the container knows based on the current scope and configuration of the application, which specific B to supply to the instance of A the container is creating for us.

Managed Extensibility Framework (MEF)

There are several IoC implementations that one can use to build their applications. Microsoft Unity and Autofac are two popular ones. In the DevForce Application Framework we are using the Managed Extensibility Framework. MEF is part of Silverlight 4 and .NET 4, so no additional assemblies need to be downloaded or included with your application. Moreover, DevForce already uses MEF for the same purpose and by using MEF in the DevForce Application Framework, we are naturally extending what DevForce already does for us. MEF also adds one powerful aspect to the mix. The ability to auto-discover component implementations dynamically at runtime without configuration of the container. This is very powerful when it comes to wanting to build your own extensible application, meaning you want to support a plug-in model for your application or simply downloading additional modules as XAP files in Silverlight for example and have the application automatically discover the contents of the downloaded XAP file.

We are not going to explain MEF in detail here. To learn about all there is to MEF, please visit the MEF documentation on CodePlex here.

So, to continue with our two classes, the following snippet shows how to implement them with MEF.

[Export]
public class A
{
    private B _objectB;

    [ImportingConstructor]
    public A(B objectB)
    {
        _objectB = objectB;
    }
}

[Export]
public class B
{
}

The basic concepts behind MEF are exports and imports. The various parts are exported using a form of the MEF ExportAttribute and then imported using a from of the MEF ImportAttribute, ImportManyAttribute or ImportingConstructorAttribute. We can then use the static CompositionHelper class or better yet, the injectable CompositionCatalogService in the DevForce Application Framework to obtain an instance of A with all its dependencies resolved.

A objectA = CompositionHelper.GetInstance<A>();

Last edited Oct 23, 2011 at 7:41 AM by marcelgood, version 17

Comments

No comments yet.