AutoMapper, отображение вложенной коллекции коллекций в список - PullRequest
0 голосов
/ 06 мая 2020

Я только начал использовать AutoMapper в основном проекте asp net и пытаюсь сопоставить объект, который имеет набор объектов, который также имеет коллекцию объектов, с сущностью.

Источник

public class MyClass
    {
        public List<MyCollection> MyCollections { get; set; }
    }

    public class MyCollection
    {
        public int CollectionId { get; set; }
        public List<Description> Descriptions { get; set; }
    }

    public class Description
    {
        public int DescriptionId { get; set; }
        public string Text { get; set; }
    }

Место назначения

 public class DescriptionToCollection
    {
        public int DescriptionId { get; set; }
        public int CollectionId { get; set; }
    }

Я играл с ConvertUsing, думая что-то вроде этого, но я не могу заставить его работать.

CreateMap<MyClass, List<DescriptionToCollection>>()
             .ConvertUsing(source => source.MyCollections.Select(x =>x.Description.Select(y=> new DescriptionToCollection{ DescriptionId=y.DescriptionId,CollectionId=x.CollectionId}).ToList()
             ));

При поиске документов AutoMappers и inte rnet я не нашел ничего похожего на мою проблему. Любая помощь приветствуется.

Ответы [ 3 ]

1 голос
/ 06 мая 2020

Попробуйте реализовать ITypeConverter, следуйте примеру кода:

Ваши классы

    public class Class1
    {
        public List<Class2> class2 { get; set; }
    }

    public class Class2
    {
        public int CollectionId { get; set; }
        public List<Class3> class3 { get; set; }
    }

    public class Class3
    {
        public int DescriptionId { get; set; }
        public string Text { get; set; }
    }


    public class ClassDto
    {
        public int DescriptionId { get; set; }
        public int CollectionId { get; set; }
    }

Пользовательская карта

    public class ClassCustomMap : ITypeConverter<Class1, List<ClassDto>>
    {

        public List<ClassDto> Convert(Class1 source, List<ClassDto> destination, ResolutionContext context)
        {
            var classDtoList = new List<ClassDto>();
            foreach (var item in source.class2)
            {
                var collectionID = item.CollectionId;
                foreach (var obj in item.class3)
                {
                    var classDto = new ClassDto();
                    classDto.CollectionId = collectionID;
                    classDto.DescriptionId = obj.DescriptionId;

                    classDtoList.Add(classDto);
                }
            }

            return classDtoList;
        }
    }

Объявление сопоставления

    CreateMap<Class1, List<ClassDto>>().ConvertUsing<ClassCustomMap>();

Как его использовать

    var class2 = new Class2();
    class2.CollectionId = 2;

    var class3 = new Class3();
    class3.DescriptionId = 1;
    class3.Text = "test";

    class2.class3 = new System.Collections.Generic.List<Class3>() { class3 };

    var class1 = new Class1();
    class1.class2 = new System.Collections.Generic.List<Class2>() { class2 };

    var result = mapper.Map<List<ClassDto>>(class1);

Для ясности и упрощения я использовал явные циклов, при желании можно оптимизировать функцию преобразования с помощью LinQ и Lambda

0 голосов
/ 06 мая 2020

Вам не хватает цели автоматического сопоставления.

Его следует использовать для преобразования входного объекта одного типа в выходной объект другого типа.

И вы хотели создать карту из типа MyClass в список - это следует рассматривать как проекцию.

Вы можете добиться этого с помощью LINQ (например, как метод расширения в MyClass):

    public static class MyClassExtension
    {
        public static List<DescriptionToCollection> ToDescriptionToCollection(this MyClass value)
        {
            return value.MyCollections.SelectMany(mc => mc.Descriptions.Select(d => new DescriptionToCollection()
            {
                CollectionId = mc.CollectionId,
                DescriptionId = d.DescriptionId
            })).ToList();
        }
    }
0 голосов
/ 06 мая 2020

Помимо опечатки в вашем примере кода, она у вас почти была. Поскольку вы не отображаете 1: 1 на верхнем уровне, вам нужно где-то сгладить, и вы делаете это, используя SelectMany, перемещая вызов ToList соответствующим образом.

CreateMap<MyClass, List<DescriptionToCollection>>()
    .ConvertUsing(source => source.MyCollections.SelectMany(x => // SelectMany to flatten
                        x.Descriptions.Select(y => 
                            new DescriptionToCollection
                            {
                                DescriptionId = y.DescriptionId,
                                CollectionId = x.CollectionId
                            }
                        ) // ToList used to be here
                    ).ToList()
                );
...