AutoMapper and IoC

Since we’re a big user of IoC containers, namely StructureMap (which was obviously a big inspiration in the design of the configuration), I tried to make AutoMapper IoC-friendly out of the box.  It wasn’t friendly at first, Jeffrey Palermo had to prod me…a few times on this one.  All of the examples of AutoMapper right now use the static Mapper class like this:

// Configure AutoMapper
Mapper.CreateMap<Order, OrderDto>();

// Perform mapping
OrderDto dto = Mapper.Map<Order, OrderDto>(order);

But the Mapper class is merely a wrapper around two classes that do the real work – the Configuration class and the MappingEngine class.  The Mapper class provides a singleton implementation of Configuration, but you’re not limited to just using Mapper.  Instead, we can configure our container to provide everything for us.  First, we need to worry about the Configuration class.

Configuring…Configuration

AutoMapper configuration, like many other configuration tasks, needs to happen only once per AppDomain, and at the startup of the application.  In a current project, we have AutoMapper, StructureMap, NHibernate, and I believe even some log4net configuration executed once at application startup.  Depending on the application environment, this could mean the Application_Start event in global.asax for ASP.NET applications, or just Main() for WinForms apps.  In any case, we have a BootStrapper class that wraps configuration for all of our tools.  This is where we can configure both our container and AutoMapper.  Since I’ve only really used StructureMap, we’ll use that as an example.

To configure the Configuration class correctly in our container (alliteration, BOOM), we need to accomplish a few things:

  • Make it singleton
  • Point requests for IConfiguration to Configuration
  • Point requests for IConfigurationProvider to Configuration
  • Set up the IObjectMapper[] dependency

The reason for the two interfaces is that AutoMapper separates the operational from the configuration interface in its semantic model.  The Configuration class depends on a set of IObjectMappers to do things like configuration validation, and the actual mapping engine will use whatever IObjectMappers we supply.  Here’s the Configuration constructor we care about:

public Configuration(IEnumerable<IObjectMapper> mappers)
{
    _mappers = mappers;
}

Thanks to a community patch, we can get the default list of mappers from a registry:

public static class MapperRegistry
{
    public static Func<IEnumerable<IObjectMapper>> AllMappers = () => new IObjectMapper[]
    {
        new CustomTypeMapMapper(),
        new TypeMapMapper(),
        new NewOrDefaultMapper(),
        new StringMapper(),
        new FlagsEnumMapper(),
        new EnumMapper(),
        new AssignableMapper(),
        new ArrayMapper(),
        new DictionaryMapper(),
        new EnumerableMapper(),
        new TypeConverterMapper(),
        new NullableMapper(),
    };
}

In case we want to supply different mappers, we can simply replace this function with something else.  It’s this location where we can provide the list of mappers for our Configuration object.  We don’t have to, as our Configuration type only depends on an enumerable collection of mappers, but this is a convenient place to pull from.

Let’s look at our StructureMap configuration for our Configuration object:

public class ConfigurationRegistry : Registry
{
    public ConfigurationRegistry()
    {
        ForRequestedType<Configuration>()
            .CacheBy(InstanceScope.Singleton)
            .TheDefault.Is.OfConcreteType<Configuration>()
            .CtorDependency<IEnumerable<IObjectMapper>>().Is(expr => expr.ConstructedBy(MapperRegistry.AllMappers));

        ForRequestedType<IConfigurationProvider>()
            .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());

        ForRequestedType<IConfiguration>()
            .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());
    }
}

In our custom StructureMap Registry, we first configure the Configuration object to be singleton, to default to the Configuration type, and configure the constructor dependency to be constructed by our mapper registry.  The next two configuration pieces set up the two semantic model interfaces to resolve to the Configuration class.  We use the “ConstructedBy” and “GetInstance” to ensure that resolutions for the two interfaces use the configuration we already set up for Configuration.  This is so both interfaces resolve to the exact same instance.

Next, we need to focus on the other major piece of AutoMapper – the mapping engine.

Configuring the mapping engine

The AutoMapper mapping engine does all the nitty gritty work of performing a mapping.  It is defined by the IMappingEngine interface, and implemented by the MappingEngine class.  Our MappingEngine class has a single dependency:

public MappingEngine(IConfigurationProvider configurationProvider)
{
    _configurationProvider = configurationProvider;
}

The MappingEngine, unlike our Configuration object, does not need any special caching/lifetime behavior.  The MappingEngine is very lightweight, as it’s really a bunch of methods doing interesting things with Configuration.  MappingEngine can be singleton if we want, but there’s no need.  Configuring the last piece for the IMappingEngine interface is very simple:

ForRequestedType<IMappingEngine>().TheDefaultIsConcreteType<MappingEngine>();

I didn’t feel like scanning the entire assembly, so I just manually set up this pair.

Putting it all together

Finally, let’s show our entire AutoMapper and StructureMap configuration:

[Test]
public void Example()
{
    ObjectFactory.Initialize(init =>
    {
        init.AddRegistry<ConfigurationRegistry>();
    });

    var configuration1 = ObjectFactory.GetInstance<IConfiguration>();
    var configuration2 = ObjectFactory.GetInstance<IConfiguration>();
    configuration1.ShouldBeTheSameAs(configuration2);

    var configurationProvider = ObjectFactory.GetInstance<IConfigurationProvider>();
    configurationProvider.ShouldBeTheSameAs(configuration1);

    var configuration = ObjectFactory.GetInstance<Configuration>();
    configuration.ShouldBeTheSameAs(configuration1);
    
    configuration1.CreateMap<Source, Destination>();

    var engine = ObjectFactory.GetInstance<IMappingEngine>();

    var destination = engine.Map<Source, Destination>(new Source {Value = 15});

    destination.Value.ShouldEqual(15);
}

In this test, I initialize StructureMap with the registry created earlier.  Next, I pull various objects from StructureMap, and do some tests to ensure that all configuration types resolve to the exact same instance.  Once I have an IConfiguration instance, I can configure AutoMapper as needed.

Once AutoMapper configuration is complete, I can query StructureMap for an IMappingEngine instance, and use it to perform a mapping operation from some source and destination object.  Note that I didn’t need to specify the IConfigurationProvider instance for the IMappingEngine resolution, StructureMap wired this dependency up for me.

But this isn’t the only way to do IoC with AutoMapper.

Scenario 2 – Keeping the static class for configuration/lifetime management

If you only want to do IoC for the mapping engine, configuration will be quite a bit shorter.  In that scenario, you basically don’t care about the Configuration class.  You use the Mapper static class to do all of your configuration, and only configure the IMappingEngine-MappingEngine pair.  This is useful if you inject IMappingEngine in places, but not Configuration.  We will let Mapper do all of our instance/lifetime management, and simply point our container to Mapper for the mapping engine.  In this case, all we need to do is point the MappingEngine’s constructor dependency to the static Mapper class ConfigurationProvider property:

public class MappingEngineRegistry : Registry
{
    public MappingEngineRegistry()
    {
        ForRequestedType<IMappingEngine>()
            .TheDefault.Is.ConstructedBy(() => Mapper.Engine);
    }
}

We do nothing more than point StructureMap to the static Mapper.Engine property for any request of an IMappingEngine type.  In our code, we configure everything through the Mapper class:

[Test]
public void Example2()
{
    ObjectFactory.Initialize(init =>
    {
        init.AddRegistry<MappingEngineRegistry>();
    });

    Mapper.Reset();

    Mapper.CreateMap<Source, Destination>();

    var engine = ObjectFactory.GetInstance<IMappingEngine>();

    var destination = engine.Map<Source, Destination>(new Source {Value = 15});

    destination.Value.ShouldEqual(15);
}

In practice, classes that need to perform a map will depend on the IMappingEngine, which, at runtime, will resolve through StructureMap simply to the static Mapper.Engine property.  In this scenario, we are able to use the Mapper static class directly for configuration, but reserve the ability to depend on an IMappingEngine when needed, where we need to make our dependencies explicit.

Much like other frameworks, the static Mapper class is merely a facade over the Configuration and MappingEngine objects, providing only instance management.  If need be, we can use any of our favorite IoC containers to manage this lifetime ourselves, eliminating a dependency on a static class.  Whether this is needed or not is up to the end user.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in AutoMapper. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.house-mixes.com Paul Hinett

    Can you provide a full working sample using Castle Windsor, i can’t seem to find any documentation / tutorials regarding automapper.

    I would really like to use it in my project but just need some beginners guidance, i can’t really make sense of the post above.

    Thank You!!

    Paul

  • http://www.candland.net/blog Dusty Candland

    Registration For Castle Windsor:

    _kernel.Register(
    Component.For().LifeStyle.Singleton.DependsOn(
    Property.ForKey(“typeMapFactory”).Eq(new TypeMapFactory()),
    Property.ForKey(“mappers”).Eq(MapperRegistry.AllMappers())),
    Component.For().ImplementedBy
    ()
    );

  • Chester

    In the ForMember, I need a service decided on the fly to the lambda expression like this
    c => c.MapFrom(s => service(s)).

    If using Moq to mock the service, it only works for the first test, the second test will fail. Why?

  • Mark Boltuc

    I have a ASP.NET MVC 2 app that has 3 main sections. Would you recommend creating a seperate MappingEngine implementation for each and sticking them in the IoC? If so, do you have a blog post that describes this? Thanks!

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Mark

    If it’s one AppDomain, and using one set of configuration, there’s no real need to have multiple mapping engines. You can separate configuration out into Profiles, however.

  • Raj

    I’m new to this and trying to understand the purpose of AutoMapper and IoC. I did a small test and found that every time I call Mapper.Configuration or Mapper.Engine, I get the same instance. So whats the purpose of IoC? Am I missing anything?


    Public Sub Test()
    Dim c1 As IConfiguration = Mapper.Configuration
    Dim c2 As IConfiguration = Mapper.Configuration

    Dim e1 As IMappingEngine = Mapper.Engine
    Dim e2 As IMappingEngine = Mapper.Engine

    Assert.AreSame(c1, c2)
    Assert.AreSame(e1, e2)
    End Sub

  • http://russ.cam.myopenid.com/ Russ Cam

    Thanks for the information.

    Do the default list of mappers have a dependency on a certain version of AutoMapper? I’ve copy/pasted them from this post and am referencing AutoMapper 1.1.0.188 but CustomTypeMapMapper and NewOrDefaultMapper are not recognised. In addition, TypeMapMapper’s constructor requires an IEnumerable. Any pointers as to how to resolve this or what I’m doing wrong?

    • http://profiles.google.com/jimmy.bogard Jimmy Bogard

      Hi Russ,

      That value is filled in by default by the static TypeMapObjectMapperRegistry.AllMappers field. If you replace that value with a new function that returns a sequence of mappers, you’re good to go. Check the source to see an example.

  • Pingback: Is the “object mother” pattern a test smell? « Look on my works, ye Mighty, and despair!

  • Peter McEvoy

    If you do wire up AutoMapper like this, I found that I could not use the static Mapper.Map(..) method – I needed to add IMappingEngine to my constructor params and get injected with the one that SM actually configured.

  • schneidr

    Jimmy, do you have any thoughts on DI of mappers as a general principle? I am personally very big on DI but the more I think about injecting mappers the more I wonder if it makes sense: The mapping code is usually so integral to the logic of the class that uses it, if you inject a mock mapping engine for unit testing you usually end up with a SUT which can accomplish very little. You then find yourself configuring the mapper mock to return predetermined things…at this point something just doesn’t seem right. I find I end up wanting to the mapping engine to behave like the real thing, not like a mock. In which case, why inject it? (or at least, why inject a mock instead of the real thing).

    • jbogard

      I don’t inject it, just like I don’t inject JSON.Net

      • schneidr

        Hehe, well thats then! :) I have worked on a few projects that injected the mapper and I must say it seemed more trouble than it was worth to mock them. Perhaps it’s worth updating this article to mention to readers that injecting *might* be an anti-pattern?

        • jbogard

          So there *is* a use case, and that’s for nested containers. If you want your IMappingEngine to have its dependencies, resolvers and type converters, resolved by the current contextual container, it’s easier with the injection method. Otherwise, you’ll have to use the Map call that overload that includes contextual options.

          • schneidr

            I can’t even conceive of such scenarios so that probably means it doesn’t apply to me! :) Presumably even in the use case above you are still injecting concrete instances of AutoMapper with mappings configured to actually do work (as opposed to mocks)?

          • jbogard

            Oh, yeah, no I don’t mock it. I only really mock components I can’t reliably control (web service, files etc). I don’t even mock a DB.

          • schneidr

            How do you ensure that a class always has the Mapper configured to its needs? Do you always call Mapper.AddProfile in it’s constructor? Is it safe to add the same profile multiple times to the singleton? I’ve just researching using NUnit’s [SetUpFixture] to add profiles globally but I don’t like the idea of knowledge of a class’ mapping requirements being needed outside of the class.

          • jbogard

            Mapping configuration only needs to happen once per AppDomain, so I put it in similar places as I would ORM configuration and IoC configuration, which similarly only needs to happen once.

          • schneidr

            Seems odd to me that the mapper the class needs in order to function is then configured outside said class. Given that we both agree the mapper is usually an ‘unchanging’ dependency (and thus we use the Mapper static) doesn’t it make more sense for the class itself to specify how it needs the Mapper to be configured to meet it’s own needs? I did a quick test and found that calling AddProfile multiple times with same profile has no ill effect, hence it seems most logical to me to put the configuration directly within the class that uses the mapper via ctor or static ctor. If you don’t agree, what am I missing?

          • Mickaël

            Just stumbled upon this conversation which I find very interesting.

            I’ve felt the same way with mappers DI, basically it’s a pain to write tests if you inject them, cause the mocking part is so uninteresting to write…

            schneidr, on that last comment, you may want to have a look at http://trycatchfail.com/blog/post/A-Better-Way-to-Configure-AutoMapper-for-ASPNET-MVC-(Video).aspx. I think this approach is very smart, as the mapping code sits next to the class needing it, but still the execution of the mapping code is done at app startup like Jimmy advises to.

            Thanks anyway, this was a very nice read.