I recently noticed some odd behavior of the AutoMapper Dynamic Map feature. Dynamic maps create some unexpected state and each map could influence all following maps in a quite severe way. See for yourself.
How to Dynamic Map
A dynamic map is a map from one class to another where you do not specify any mappings. Initialize the Mapper with CreateMissingTypeMaps = true
and ValidateInlineMaps = false
.
AutoMapper.Mapper.Initialize(cfg => {
cfg.CreateMissingTypeMaps = true;
cfg.ValidateInlineMaps = false; });
Map an object of Model
to class A
. This will create a new instance of A
and try to map all properties.
var model = new Model { Message = "Hello World" };
var a = AutoMapper.Mapper.Map<A>(model); // a.Message == "Hello World"
You can also map to an existing object and overwrite all properties that AutoMapper can map.
var model = new Model { Message = "Hello World" };
var a = AutoMapper.Mapper.Map(model, new A { Message = "Something" }); // a.Message == "Hello World"
How base class mappings destroy mapping for derived classes
When performing a dynamic map AutoMapper stores the dynamically created mapping configuration in the background. This behavior adds some unexpected state to the mapping. Depending on what mappings have already been done before the same dynamic map might now behave differently!
For some reason an already saved base-class mapping configuration will also be used for any derived classes.
class BaseClass {}
class A : BaseClass {
public string Message {get;set;}
}
Usually AutoMapper dynamically creates a map for class A
and maps all properties.
var model = new Model { Message = "Hello World" };
var a = AutoMapper.Mapper.Map(model, new A()); // a.Message == "Hello World"
However, when AutoMapper finds an already existing map for BaseClass it will use this. Since BaseClass does not have a property Message
it will now not be mapped.
var model = new Model { Message = "Hello World" };
AutoMapper.Mapper.Map(model, new BaseClass()); // dynamically creates and stores the BaseClass map
var a = AutoMapper.Mapper.Map(model, new A()); // a.Message == NULL!
This is really dangerous and unexpected and therefore Dynamic Mapping should never be used!
How to deal with this?
Don’t ever use dynamic map. That’s my new opinion since I debugged into this issue.
Secondly, I would challenge if AutoMapper is really needed at all. I know feelings are always running high when it comes to AutoMapper and my colleagues all know that I’m not a huge fan. However, it’s not that I think it is a bad tool or even hate it, I just never saw a project where it was used the way it is intended to be used.
When you want to use it make extra sure that you use it correctly - it’s a powerful tool and misuse will be punished later on.
Make sure to follow Jimmy Bogard’s AutoMapper Usage Guidelines.
Did you stumble across any unexpected problems with AutoMapper yourself? Let me know in the comments.