Automapper together with Dependency Injection

Femaref picture Femaref · Nov 17, 2010 · Viewed 24.5k times · Source

I currently have the following mapping:

Mapper.CreateMap<Journal, JournalDto>();

Now, Journal contains a member named RefTypeID, which corresponding value exists in another table in the database; to look up this value, I have a service which handles a simple int -> string request. The automapper configuration currently happens in a static class at the start of the program. Is it okay to move the mapping code into a class which gets injected into my DI container or is there a better way?

Answer

Jimmy Bogard picture Jimmy Bogard · Dec 13, 2011

A better way is to use a customer resolver. Mapping configuration is intended to be static, so custom resolvers are intended to provide mapping for a single member:

Mapper.Initialize(cfg => {
    cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type));

    cfg.CreateMap<Journal, DisplayJournal>()
        .ForMember(dest => dest.RefTypeName, 
            opt => opt.ResolveUsing<RefTypeNameResolver>());
});

Then your resolver becomes:

[Export(typeof(IRefTypeNameResolver))]
public class RefTypeNameResolver : ValueResolver<Journal, string>, IRefTypeNameResolver
{
    private readonly IRefTypesLookup iRefTypesLookup;

    [ImportingConstructor]
    public RefTypeNameResolver (IRefTypesLookup rtl)
    {
        iRefTypesLookup = rtl;
    }

    protected override string ResolveCore(Journal source)
    {
        return iRefTypesLookup.Lookup(source.RefTypeID);
    }
}

Configuration needs to execute once, which is why the configuration API provides hooks into the execution API (type converters, value resolvers etc.)