简体   繁体   English

AutoMapper,将 collections 的嵌套集合映射到列表

[英]AutoMapper, Mapping a nested collection of collections to List

I have just started using AutoMapper on an asp net core project and I'm trying to map an object that has a collection of an object that also has a collection of an object to an entity. I have just started using AutoMapper on an asp net core project and I'm trying to map an object that has a collection of an object that also has a collection of an object to an entity.

The source来源

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; }
    }

The destination目的地

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

I've played around with ConvertUsing thinking something like this, but I can't make it work.我玩过 ConvertUsing 这样的想法,但我无法让它发挥作用。

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

Searching AutoMappers docs and the internet, I couldn't find anything similar to my problem.搜索 AutoMappers 文档和互联网,我找不到与我的问题类似的任何内容。 Any help is highly appreciated.非常感谢任何帮助。

Try to implement ITypeConverter, follow the example code:尝试实现 ITypeConverter,按照示例代码:

Your Classes你的课

    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; }
    }

The custom map定制 map

    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;
        }
    }

The mapping declaration映射声明

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

How to use it如何使用它

    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);

For clarity and to simplify I have used explicit cycles, if you want you can optimize the conversion function using LinQ and Lambda为了清楚和简化,我使用了显式循环,如果您愿意,可以使用 LinQ 和 Lambda 优化转换 function

Besides a typo in your example code, you almost had it.除了您的示例代码中的错字之外,您几乎有它。 Because you aren't mapping 1:1 at the top level, you need to flatten somewhere, and you do that using SelectMany , moving the ToList call appropriately.因为您没有在顶层进行 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()
                );

You are missing the purpose of auto-mapper.您缺少自动映射器的目的。

It should be used for transforming an input object of one type into an output object of a different type.它应该用于将一种类型的输入 object 转换为不同类型的 output object。

And you wanted to create a map from MyClass type to List - this should be treated as projection.并且您想创建一个从 MyClass 类型到 List 的 map - 这应该被视为投影。

You can achieve that using LINQ (for example as a extension method on 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();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM