33

我现在正在查找AutoMapper代码(为我正在从事的项目之一评估它),坦率地说,我很惊讶:

  • 库 API 基于单个静态访问点(Mapper类型),因此通常它的任何方法都必须是线程安全的
  • 但我没有在代码中找到任何证据。

我所能找到的只是这个问题,但即使是那里的陈述似乎也不正确:如果Map内部不使用线程安全的数据结构,它也不能被认为是线程安全的,如果我要CreateMap在非并发上下文中调用,但同时与Map.

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

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

显然,如果我是正确的,那将是一个巨大的缺陷。

所以我有两个问题:

  • 我对么?
  • 如果是,那么没有此问题的 AutoMapper 的最佳替代方案是什么?
4

2 回答 2

36

链接的问题或多或少地回答了您的问题:

Mapper.CreateMap 不是线程安全的,以后也不会。但是, Mapper.Map 是线程安全的。Mapper 静态类只是 MappingEngine 和 Configuration 对象之上的一个薄包装器。

因此,仅Mapper.CreateMap当您以线程安全的方式在一个中心位置进行配置时才使用。

你的评论是:

我问这个是因为我想就地配置自动机,即在使用之前。我打算在非并发上下文中配置它,即 ~ 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);

它需要更多代码,但您可以围绕它创建自己的助手。但是在给定的方法中,一切都是本地的,因此没有共享状态,无需担心线程安全。

于 2012-05-18T09:55:05.700 回答
0

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

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

MapperConfiguration创建新的mapper实例,并将配置记录在自己的实例内存空间中。

TLDR;

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

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

于 2017-02-01T03:26:14.580 回答