2012-05-18 52 views
29

现在我仰视AutoMapper代码(评估它的我的工作项目之一),而且,坦率地说,我很惊讶:AutoMapper中的Mapper.Map是否线程安全?

  • 库API是基于一个静态接入点(Mapper类型),所以通常它的任何方法都必须是线程安全的
  • 但我没有在代码中找到任何这方面的证据。

所有我能找到是this issue,但即使在发言中似乎有不正确的:如果Map不使用线程安全的数据结构的内部,它不能也视为线程安全的,如果我打算在非并发上下文中调用CreateMap,但要同时拨打Map

I.e.在例如AutoMapper中唯一可能的使用模式ASP.NET MVC应用程序是:

lock (mapperLock) { 
    ... Mapper.AnyMethod(...) ... 
} 

显然,如果我是正确的,这是一个巨大的缺乏。

所以我有两个问题:

  • ,对吗?
  • 如果是的话,AutoMapper的最佳替代方案是什么?
+0

主要关键似乎是通过'ThreadSafeList _typeMaps'进行的双重检查;是什么让你觉得它不是线程安全的?你认为什么***特别是不是线程安全的? –

+0

TypeMap是一个不可变的对象吗? –

+0

你告诉我! (并且问题也是:即使不是,在任何时候都不恰当地更新,除了你)。你声称它不是线程安全的;请详细说明你认为不安全的事情。请注意,通常策略(一旦构建)未更新,因此唯一需要保护的是访问战略缓存,这似乎是正确完成的。 –

回答

32

链接的issue或多或少地回答你的问题:

Mapper.CreateMap不是线程安全的,也永远是。但是, Mapper.Map是线程安全的。 Mapper静态类只是MappingEngine和Configuration对象之上的一个精简包装器。

所以只能使用Mapper.CreateMap如果你在一个线程安全的方式做你的配置一个中心位置

您的评论是:

我问这个,因为我想就地使用前右侧配置automatter, 即。我计划将其配置为非并发的 上下文,即〜lock(mapperConfigLock){Mapper.CreateMap()....; }, ,我担心现在还不够。

如果您正在进行就地配置,请不要使用静态Mapper类。由于在GitHub的问题上意见建议使用直接映射引擎:

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); 

它的更多的代码一点点,但你可以围绕它创建自己的助手。 但是,在一个给定的方法中,所有东西都是本地的,所以没有共享状态不需要担心线程安全。

+0

清除,非常感谢! –

+0

'以线程安全的方式处理一个中心位置' - 我认为无论如何都需要在问题中进行解释,因为可能会出现很多错误。 –

+0

@nemesv - 非常感谢,您的解决方案真的很有帮助! – Ronnix

0

这个问题可能有些过时,只是想在一点点调查后记录一些我的发现。

Mapper是一个包装类,用于包装以创建新配置,以及静态内存中的mapper新实例,所以严格来说它不是线程安全的,但只要您只初始化配置一次,就可以使用它。

MapperConfiguration创建映射器的新实例,并将配置记录到其自己的实例内存空间中。

TLDR;

如果需要一次性初始化配置,选择静态API

如果需要初始化配置了很多次,担心线程安全,选择例如API