Возврат всех элементов в исходном списке при использовании automapper для сопоставления с существующим списком - PullRequest
0 голосов
/ 15 октября 2019

У меня есть список объектов, которые загружаются из базы данных, давайте назовем их «MyObjects», затем у меня есть список объектов расширений «ExtensionsObjects», которые загружаются из отдельной базы данных. Я использую automapper, чтобы отобразить некоторые свойства этих объектов расширения в «MyObjects». (Объект расширения содержит ключевое поле для MyObject)

Это работает, поля правильно отображаются из ExtentionObject в MyObject, но автоматический обработчик возвращает список, который возвращает только те «MyObjects», в которые был отображен «ExtensionObject». (и MyObject без объекта Extention является совершенно допустимой ситуацией).

Код, который я использую для сопоставления:

//first get the lists of MyObjects and ExtentionObjects
List<MyObject> myObjects = GetMyObjects(); 
List<ExtentionObject> extentionObjects = GetExtentionObjects(); 

//execute the mapping (_mapper is my automapper)
myObjects = _mapper.Map(extentionObjects, myObjects); 

//myObject now contains less objects than before the call to the mapper

Код для конфигурации автоматического устройства (cfg является средством отображения). конфигурация, используемая для создания сопоставителя):

cfg.CreateMap<ExtentionObject, MyObject>()
    .EqualityComparison((eo, my)=> CheckForEquality(eo, my))
    .ForMember(....)
    .ForMember(....)
    .ReverseMap().ConvertUsing((mo, eo)=> 
    {
        var ext = new ExtentionObect();
        ...
        return ext;
    });

Функция проверки на равенство просто проверяет, совпадают ли идентификаторы ExtentionObject и MyObject.

Я хочу, чтобы результирующий список содержал все элементы, которыегде в оригинальном списке «myObjects». Информация в экземплярах ExtentionObject должна быть добавлена ​​в соответствующие экземпляры MyObject, но поскольку расширение является необязательным, все «MyObjects» должны оставаться в результирующем списке.

Допустим, моя база данных содержит MyObjects с ключами 1, 2,3и ExtentionObjects с ключом 1 и 3.

//before this cal myObjects contains 3 items, ExentionObjects contains 2
myObjects = _mapper.Map(extentionObjects, myObjects); 
//after this cal myObjects contains only 2 items, 
//with the properties from Extentionobject 1 and 3 correctly mapped to MyObject 1 and 3, 
//ERROR => MyObject 2 has "disappeared" from the 'destination' list

Вопрос «Как сохранить объект 2 в моем списке»?

1 Ответ

0 голосов
/ 16 октября 2019

После дальнейших исследований выяснилось, что проблема не в самом Automapper, а в Automapper.Collections (расширение autopper для отображения коллекций). Проблема с той же функциональностью была поднята на его github repo , но реального решения не существует. Хотя есть совет относительно того, как изменить automapper.collection, чтобы избежать удаления, но я не думаю, что разветвление этого хранилища целесообразно в долгосрочной перспективе. Тем не менее, существует указание на то, где элементы удаляются из списка. Он использует метод ICollection.Remove () (не понятный, а затем добавляет значения).

Поэтому мое решение заключается в том, чтобы обернуть мой список в «EditOnlyCollection», который имеет реализацию «nop» для «Remove». (В моем случае есть также «нет» для других методов, но это легко изменить). Примечание. Он не работает со сборкой в ​​ReadOnlyCollection, поскольку он вызывает исключения в методе удаления.

class EditOnlyCollection<T> : ICollection<T>
    {
        private readonly List<T> list;

        public EditOnlyCollection(IEnumerable<T> list)
        {
            this.list = list.ToList();
        }

        public int Count => list.Count;

        public bool IsReadOnly => true;

        public void Add(T item)
        {
            //nop
        }

        public void Clear()
        {
            //nop
        }

        public bool Contains(T item)
        {
            return list.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            list.CopyTo(array, arrayIndex);
        }

        public IEnumerator<T> GetEnumerator()
        {
            return list.GetEnumerator();
        }

        public bool Remove(T item)
        {
            //nop
            return true; //have them think we removed an item
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return list.GetEnumerator();
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...