Make your project pluggable with StructureMap

UPDATE: This post has been updated to account for the StructureMap API changes that happened sometime around StructureMap 2.5.4.

We all know that StructureMap is great for implementing dependency injection in your application, making your app more testable, and all that. But StructureMap can do so much more than that. StructureMap can help you create pluggable project architectures that can allow you easily modify how your application works in certain situations with minimal to no configuration.

layersLet me explain. Most people have some kind of layered setup in their projects. The basic architecture is 3 tiers — a UI layer, a business layer, and a data access layer.

Entity objects are going to flow through these layers. You will load, save, and delete entities. And in most cases, the way that you load, save, and delete these entities will be the same — but not always the same.

What we want to do is write code to handle the normal entities and write it just once. If we need to modify how things are done for a certain entity, then we’ll write code for that. By doing it this way, we should have little or no code duplication.

The diagram on the right shows our project structure. You will notice that we have some generic interfaces defined in the business layer and data access layer. That classes that implement these interfaces will perform the specified actions using an entity (the generic parameter T in each interface).

Here’s an example. The IRepository<T> interface contains methods that will talk to the database. I will create a concrete class called Repository<T> that implements the standard method of talking to the database. This is how most of our entities will be loaded, saved, and deleted.

public interface IRepository where T : class
{
    T Get(long id);
    IList GetAll();
    void Save(T target);
    void Delete(T target);
}

public class Repository : IRepository where T : class
{
    public T Get(long id)
    {
        // do stuff here
    }

    public IList GetAll()
    {
        // do stuff here
    }

    public void Save(T target)
    {
        // do stuff here
    }

    public void Delete(T target)
    {
        // do stuff here
    }
}

Let’s say that I have a Customer entity that is persisted to a different database than the rest of the application. I now have a special case where I need to write custom repository code for a Customer. So I’ll make a class called CustomerRepository and have it implement IRepository<Customer>.

public class CustomerRepository : IRepository
{
    public Customer Get(long id)
    {
        // do custom stuff here
    }

    public IList GetAll()
    {
        // do custom stuff here
    }

    public void Save(Customer target)
    {
        // do custom stuff here
    }

    public void Delete(Customer target)
    {
        // do custom stuff here
    }
}

Here’s where StructureMap comes in. I’m going to configure StructureMap so that I can ask for IRepository<T> for some entity T and it will give me back the correct concrete class. This means:

IRepository<Product> maps to Repository<Product>
IRepository<Order> maps to Repository<Order>
IRepository<WhateverOtherEntity> maps to Repository<WhateverOtherEntity>
IRepository<Customer> maps to CustomerRepository (because CustomerRepository implements IRepository<Customer>)

Look at how easy this is going to be! I’m not going to have to do any extra configuration or wiring up to change how Customer entities are persisted. I’m not going to write any extra plumbing code, I’m just going to create the CustomerRepository class and implement an interface, and now my app deals with Customer objects differently.

Obviously there is some fancy plumbing going on behind the scenes, so let’s see how we set this up.

It’s really not that hard, actually, because most of the hard work is done by StructureMap. We just have to do some simple configuration.

Here’s how we initialize StructureMap:

public class StandardStructureMapConfiguration
{
    public void Configure()
    {
        ObjectFactory.Initialize(x =>
        {
            x.Scan(scan =>
            {
                // Automatically maps interface IXyz to class Xyz
                scan.WithDefaultConventions();
                scan.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
                scan.ConnectImplementationsToTypesClosing(typeof(IGetObjectService<>));
                scan.ConnectImplementationsToTypesClosing(typeof(ISaveObjectService<>));
                scan.ConnectImplementationsToTypesClosing(typeof(IDeleteObjectService<>));

                scan.Assembly(GetType().Assembly);
            });

            x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
            x.For(typeof(IGetObjectService<>)).Use(typeof(GetObjectService<>));
            x.For(typeof(ISaveObjectService<>)).Use(typeof(SaveObjectService<>));
            x.For(typeof(IDeleteObjectService<>)).Use(typeof(DeleteObjectService<>));
        });
    }
}

Let’s break this down and go over what I’m doing here.

scan.WithDefaultConventions();

This tells StructureMap to automatically map an interface IXyz to class Xyz. Most of the time, the names of your interfaces are just the concrete class with an “I” slapped on the front. This only applies to non-generic classes, so this isn’t necessarily helping us with our IRepository<T> example, but I do it on every project, so I thought I’d throw it in.

scan.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
scan.ConnectImplementationsToTypesClosing(typeof(IGetObjectService<>));
scan.ConnectImplementationsToTypesClosing(typeof(ISaveObjectService<>));
scan.ConnectImplementationsToTypesClosing(typeof(IDeleteObjectService<>));

We don’t just want to use the default conventions, we want to tell StructureMap to map concrete classes that implement generic interfaces. Basically all we’re doing here is telling StructureMap that if I have a custom concrete class that implements one of these generic interfaces, we want to automatically wire those up.

scan.AssemblyContainingType(GetType().Assembly);

We want StructureMap to look inside the specified assembly and apply the conventions to the types in this assembly. You can also do scan.AssemblyContainingType<T>.

x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
x.For(typeof(IGetObjectService<>)).Use(typeof(GetObjectService<>));
x.For(typeof(ISaveObjectService<>)).Use(typeof(SaveObjectService<>));
x.For(typeof(IDeleteObjectService<>)).Use(typeof(DeleteObjectService<>));

Here we are wiring up the generic interfaces to the default concrete implementations of each interface. This is for the 95% of the time when we’re using the normal way of doing these things.

StructureMap needs to be initialized whenever your application starts (Program.cs for WinForms, App.xaml.cs for WPF, Global.asax Application_Start() for web apps). So in this case, I would new up an instance of the StandardStructureMapConfiguration class that I created here and call the Configure() method, which would do all of the ObjectFactory.Initialize() stuff.

I created a small sample project with this code. This is really easy to implement and it makes development a lot easier by reduces the amount of tedious plumbing code that you need to write.