Является ли Mapper.Map в AutoMapper потокобезопасным?
Я просматриваю AutoMapper код (оценивая его для одного из проектов, над которыми я работаю), и, честно говоря, Я очень удивлен:
- API-интерфейс библиотеки основан на единой статической точке доступа (тип
Mapper
), поэтому, как правило, любой из ее методов должен быть потокобезопасным
- Но я не нашел никаких доказательств этого в коде.
Все, что мне удалось найти, это этот вопрос, но даже сделанное утверждение кажется неправильным: if Map
не использует поток -сохраняемые структуры данных, они не могут рассматриваться как поточно-безопасные, если я собираюсь называть CreateMap
в неконкурентном контексте, но одновременно с Map
.
т.е. единственный возможный шаблон использования AutoMapper, например. Приложение ASP.NET MVC:
lock (mapperLock) {
... Mapper.AnyMethod(...) ...
}
Очевидно, если я прав, это огромный недостаток.
У меня есть два вопроса:
- Правильно ли я?
- Если да, то какая лучшая альтернатива AutoMapper, которая не имеет этой проблемы?
Ответы
Ответ 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