Вызов IMappingEngine.Map внутри пользовательского сопоставления - PullRequest
4 голосов
/ 14 февраля 2012

При использовании 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?

Ответы [ 2 ]

3 голосов
/ 23 февраля 2012

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

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

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

(Обновленный пример кода IOC для последней версии Automapper на github )

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

Исходя из вышеизложенного, кроме того, что вы не зарегистрировали ConfigurationStore как одноэлементный экземпляр (я полагаю, я не знаком с 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 в вспомогательном контейнере со свойством Mapper.Engine.

0 голосов
/ 23 февраля 2012

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

...