I'm looking up AutoMapper code now (evaluating it for one of projects I'm working on), and, frankly speaking, I'm quite surprised:
Mapper
type), so generally any of its methods must be thread safeAll I was able to find is this issue, but even the statement made there seems incorrect: if Map
doesn't use thread-safe data structures internally, it can't be considered as thread-safe as well, if I'm going to call CreateMap
in non-concurrent context, but concurrently with Map
.
I.e. the only possible usage pattern of AutoMapper in e.g. ASP.NET MVC application is:
lock (mapperLock) {
... Mapper.AnyMethod(...) ...
}
Obviously, if I'm correct, that's a huge lack.
So I have two questions:
1. If you use the convention-based mapping and a property is later renamed that becomes a runtime error and a common source of annoying bugs. 2. If you don't use convention-based mapping (ie you explicitly map each property) then you are just using automapper to do your projection, which is unnecessary complexity.
Yes, or you can call CreateMap<ModelClass, ViewModelClass>(). ReverseMap() .
Automatically-mapped Properties are now case sensitive · Issue #950 · AutoMapper/AutoMapper · GitHub.
The linked issue more or less answers your questions:
Mapper.CreateMap is not threadsafe, nor will it ever be. However, Mapper.Map is thread-safe. The Mapper static class is just a thin wrapper on top of the MappingEngine and Configuration objects.
So only use Mapper.CreateMap
if you do your configuration in one central place in a threadsafe manner.
Your comment was:
I'm asking this because I'd like to configure automatter in-place, i.e. right before usage. I planned to configure it in non-concurrent context, i.e. ~ lock (mapperConfigLock) { Mapper.CreateMap()....; }, and I fear this is not enough now.
If you are doing in-place configuration just don't use the static Mapper
class. As the comment on the github issue suggest use the mapping engine directly:
var config = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.AllMappers()); config.CreateMap<Source, Destination>(); var engine = new MappingEngine(config); var source = new Source(); var dest = engine.Map(source);
It's a little bit of more code but you can create your own helpers around it. But everything is local in a given method so no shared state no need to worry about thread safety.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With