Вызов IMappingEngine.Map внутри пользовательского сопоставления

С AutoMapper при использовании ConvertUsing для определения пользовательского сопоставления для типа, который является контейнером, мне часто приходится вызывать IMappingEngine.Map внутри функции сопоставления. Это необходимо, потому что позволяет повторно использовать определение дочернего отображения.

CreateMap<Order, OrderModel>()
    .ConvertUsing(o => new OrderModel(
        o.Id,
        o.ShippingAddress,
        mapper.Map<IList<OrderItemModel>>(o.Items)
    ));

Для этого мне нужна ссылка на IMappingEngine. Когда механизм сопоставления настраивается, у меня нет ссылки на него, которую можно было бы зафиксировать в аргументе ConvertUsing. Простое решение состоит в том, чтобы где-то иметь статическую ссылку на него, но я бы хотел этого избежать.

Есть ли способ получить ссылку на текущий IMappingEngine внутри сопоставления, использующего ConvertUsing?


person Antoine Aubry    schedule 14.02.2012    source источник
comment
просто любопытно, почему это помечено как внедрение зависимостей?   -  person Jonathan S. Fisher    schedule 22.02.2012
comment
Это ошибка. Спасибо, что заметили это. Я переписал этот вопрос и удалил часть его, потому что это усложнило его. В основном эта проблема становится более очевидной при использовании внедрения зависимостей для создания картографа и его конфигурации.   -  person Antoine Aubry    schedule 22.02.2012


Ответы (2)


Этот ответ основан на вашей исходной версии, которая включала дополнительный код

Если вы посмотрите на статью Джимми Богарда о Automapper и IOC он отмечает следующее:

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

(На есть обновленный пример кода IOC для последней версии Automapper. гитхаб)

Пока ваш ConfigurationStore является синглтоном, а запросы на IConfiguration и IConfigurationProvider из контейнера DI разрешаются в этот экземпляр синглтона, в статье (и примерах кода) рекомендуется создавать новые экземпляры MappingEngine при внедрении.

Основываясь на вышеизложенном, помимо того, что вы не регистрируете свой ConfigurationStore как экземпляр singleton (я предполагаю, что я не знаком с ninject) и не привязываете этот экземпляр к IConfiguration, ваша окончательная реализация MappingProfile в исходной версии является приемлемым решением. Это нормально, если это не один и тот же экземпляр MappingEngine.

Однако, исходя из вашего примера использования в вашем вопросе, возможно, стоит рассмотреть Сценарий 2 в статье. Если у вас нет необходимости внедрять конфигурацию во все приложения, а требуется только IMappingEngine, вы можете положиться на статический класс Mapper для управления конфигурацией и сроком службы. Таким образом, ваши изменения для принятия этого будут следующими:

  1. Удалите проводку, связанную с IConfigurationProvider, в сборке вашего контейнера (в MappingModule).

  2. Переключение вашего MappingProfile на использование статического класса Mapper

    CreateMap<Order, OrderModel>()
        .ConvertUsing(o => new OrderModel(
            o.Id,
            o.ShippingAddress,
            Mapper.Map<IList<OrderItemModel>>(o.Items) //use static Mapper class
    ));
    
    CreateMap<OrderItem, OrderItemModel>();
    
  3. Добавление Profile к Mapper (возможно, в MappingModule?) и выполнение любых других настроек через Mapper:

    Mapper.AddProfile(new MappingProfile());
    
  4. Привязка IMappingEngine в контейнере ninject к свойству Mapper.Engine.

person Pero P.    schedule 22.02.2012
comment
Основная проблема заключается в том, что для создания IMappingEngine мне нужен IMappingEngine, а для создания IMappingEngine мне нужен IMappingEngine. Использование статического картографа скрывает эту проблему, но не решает ее. Я могу создать пустую конфигурацию, создать с ее помощью механизм сопоставления, а затем настроить конфигурацию с помощью механизма сопоставления, но это зависит от того факта, что MappingEngine допускает изменение конфигурации после ее создания. - person Antoine Aubry; 23.02.2012
comment
Я не уверен, что следую. Карты — это просто серия лямбда-выражений, выполняемых во время сопоставления экземпляра. Пока MappingEngine на вашей вложенной карте использует тот же ConfigurationStore, который настраивается (то есть синглтон), это не проблема во время сопоставления. По той же причине вы можете определить CreateMap вне порядка их использования, как вы это сделали в своем Profile. - person Pero P.; 23.02.2012

Вы можете использовать статический Mapper.Map<IList<OrderItemModel>>(o.Items) вместо своего экземпляра IMappingEngine. Он содержит ссылку на движок, который лениво создается при первом использовании.

person Steve Czetty    schedule 22.02.2012
comment
Да, это работает, но я бы предпочел избегать использования статического класса Mapper. - person Antoine Aubry; 23.02.2012
comment
тоже самое, решения тоже не нашел - person juFo; 02.02.2016