· automapper

Automapper: Don't forget Mapper.Reset() at the start

I wrote about my first thoughts using Automapper last week and although I realised that it makes use of the static gateway pattern we ran into a problem where two consecutive calls to a method using AutoMapper always returned the same value for one of the mappings.

The code was roughly like this:


public Bar CreateNewBar(Bar originalBar, string someNewValue)
{
	Mapper.CreateMap<Baz, Baz>()
      .ForMember(x => x.Id, opts => opts.Ignore())
      .ForMember(x => x.SomeProperty, opts => opts.MapFrom(source => someNewValue));
}

In our test everything worked fine because we were only calling the method once but when testing it out we were making multiple calls to the method and always receiving the same value for ‘someNewValue’.

I hadn’t quite pieced together that each mapping was probably only created once for each source/destination pair. I thought it would be recreated each time but browsing through the code we can see that’s what’s going on:

Configuration.cs


public IMappingExpression CreateMap(Type sourceType, Type destinationType)
{
   var typeMap = CreateTypeMap(sourceType, destinationType);

   return new MappingExpression(typeMap, _serviceCtor);
}

public TypeMap CreateTypeMap(Type source, Type destination)
{
   TypeMap typeMap = FindExplicitlyDefinedTypeMap(source, destination);
				
   if (typeMap == null)
   {
   ...
   }
   return typeMap;
}

private TypeMap FindExplicitlyDefinedTypeMap(Type sourceType, Type destinationType)
{
   return _typeMaps.FirstOrDefault(x => x.DestinationType == destinationType && x.SourceType == sourceType);
}

We put a test which called the method ‘CreateNewBar’ method twice to make sure that was actually the problem and then made use of the ‘Reset’ method on ‘Mapper’ to avoid the problem:


public Bar CreateNewBar(Bar originalBar, string someNewValue)
{
    Mapper.Reset();
	Mapper.CreateMap<Baz, Baz>()
      .ForMember(x => x.Id, opts => opts.Ignore())
      .ForMember(x => x.SomeProperty, opts => opts.MapFrom(source => someNewValue));
}
  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket