Подтвердить что ты не робот

Является ли Mapper.Map в AutoMapper потокобезопасным?

Я просматриваю AutoMapper код (оценивая его для одного из проектов, над которыми я работаю), и, честно говоря, Я очень удивлен:

  • API-интерфейс библиотеки основан на единой статической точке доступа (тип Mapper), поэтому, как правило, любой из ее методов должен быть потокобезопасным
  • Но я не нашел никаких доказательств этого в коде.

Все, что мне удалось найти, это этот вопрос, но даже сделанное утверждение кажется неправильным: if Map не использует поток -сохраняемые структуры данных, они не могут рассматриваться как поточно-безопасные, если я собираюсь называть CreateMap в неконкурентном контексте, но одновременно с Map.

т.е. единственный возможный шаблон использования AutoMapper, например. Приложение ASP.NET MVC:

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

Очевидно, если я прав, это огромный недостаток.

У меня есть два вопроса:

  • Правильно ли я?
  • Если да, то какая лучшая альтернатива AutoMapper, которая не имеет этой проблемы?
4b9b3361

Ответ 1

Связанная проблема более или менее отвечает на ваши вопросы:

Mapper.CreateMap не является потокобезопасным, и он никогда не будет. Однако, Mapper.Map является потокобезопасным. Статический класс Mapper является просто тонким обертка поверх объектов MappingEngine и Configuration.

Поэтому используйте Mapper.CreateMap, если вы выполняете свою конфигурацию в одном центральном месте в потоковом режиме.

Ваш комментарий:

Я спрашиваю об этом, потому что я хотел бы настроить automater на месте, т.е. прямо перед использованием. Я планировал настроить его в неконкурентных контекст, т.е. блокировка (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);

Это немного больше кода, но вы можете создать вокруг себя своих помощников. Но все локально в данном методе, поэтому ни одно общее состояние не должно беспокоиться о безопасности потоков.

Ответ 2

Эти вопросы могут быть немного устаревшими, просто хочу записать некоторые мои выводы после небольшого расследования.

Mapper - это класс оболочки для переноса, чтобы создать новую конфигурацию, и новый экземпляр mapper внутри статической памяти, так строго говоря не является потокобезопасным, но вы можете использовать его в безопасности до тех пор, пока вы только инициализируете конфигурацию один раз.

MapperConfiguration создать новый экземпляр mapper и записать конфигурацию внутри своего собственного пространства памяти экземпляра.

TL;DR;

Если вам нужно только настроить конфигурацию только один раз, выберите статический API

Если вам нужно много раз инициализировать конфигурацию и беспокоиться о безопасности потока, выберите экземпляр API