Почему AutoMapper использует мою конфигурацию только для первого элемента в списке? - PullRequest
2 голосов
/ 16 марта 2011

Вот моя конфигурация AutoMapper:

Mapper.CreateMap<Source, Destination>()
      .ConstructUsing(s => new Destination(s.CreatedDate.DateTime));

Оба класса имеют одно свойство, CreatedDate, но они бывают разных типов:

public class Source
{
   public DateTimeOffset CreatedDate { get; set; }
}

public class Destination
{
   public Destination(DateTime created) { CreatedDate = created; }
   public DateTime CreatedDate { get; set; }
}

Эта конфигурация прекрасно работает, когда я сопоставляю экземпляры одного экземпляра другому, но возникает проблема, когда я сопоставляю перечислимые типы этих типов, как в:

var dests = Mapper.Map<IEnumerable<Source>, Destination[]>(sources);

В этом случае AutoMapper вызывает конструктор Destination для первого элемента, который должен быть отображен, но, очевидно, переходит к автоматическому сопоставлению остальных элементов. Автоматическое сопоставление вызывает исключение, поскольку свойства CreatedDate с одинаковыми именами относятся к разным типам.

Если я изменю имя одного из свойств - скажем, Destination.Created - конструктор вызывается для всех элементов, как и следовало ожидать.

Я использую последнюю версию AutoMapper (v1.1.0.188). Кажется, это ошибка, но, может быть, я что-то упустил?

Ответы [ 3 ]

1 голос
/ 21 марта 2011

Мне показалось неестественным по какой-либо причине, но, очевидно, ConstructUsing только определяет, как построить сопоставленный объект, и не влечет за собой никаких конкретных правил сопоставления (или их отсутствия) по умолчанию. А поскольку сопоставление по умолчанию копирует значения из одноименных свойств, мой элемент CreatedDate копировался автоматически.

Решение состоит в том, чтобы просто предоставить соответствующие правила отображения в дополнение к правилу построения. В моем случае, поскольку все мои сопоставления выполняются во время конструирования, просто нужно пропустить сопоставление для свойства с таким же именем:

Mapper.CreateMap<Source, Destination>()
      .ConstructUsing(s => new Destination(s.CreatedDate.DateTime))
      .ForMember(d => d.CreatedDate, opt => opt.Ignore());
1 голос
/ 12 февраля 2015

Я столкнулся с этим вопросом, когда искал лучший способ автоматизировать переход от DateTimeOffset к DateTime.Я не знаю о более ранних версиях AutoMapper, но в AutoMapper 3.2.1 мне удалось создать карту между DateTimeOffset и DateTime, и AutoMapper будет автоматически использовать ее всякий раз, когда сталкивается с указанной ситуацией.

ДляНапример, следующий код преобразует DateTimeOffset в DateTime с использованием свойства DateTimeOffset.UtcDateTime:

Mapper.CreateMap<DateTimeOffset, DateTime>().ConvertUsing(d => d.UtcDateTime);

Как только вышеуказанная карта зарегистрирована в AutoMapper, она преобразует с использованием данного выражения независимо от того, какой объект содержитзначения для преобразования между.

Надеюсь, это поможет любому, кто сталкивается с этой ситуацией, используя более новую версию AutoMapper.

1 голос
/ 16 марта 2011

Возможно, вы захотите попробовать другой подход.Я бы попробовал:

Mapper.CreateMap<Source, Destination>()
      .ForMember(d => d.CreatedDate,
                 opt => opt.MapFrom(s => s.CreatedDate.DateTime));

Отображение немного более многословно, но оно должно обрабатываться правильно для каждого элемента.Более того, теперь вы можете удалить лишний конструктор в вашем классе Destination.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...