【问题标题】:AutoMapper, Mapping a nested collection of collections to ListAutoMapper,将嵌套的集合集合映射到列表
【发布时间】:2020-05-06 14:31:04
【问题描述】:

我刚刚开始在一个 asp net core 项目上使用 AutoMapper,我正在尝试将一个具有一个对象集合的对象映射到一个实体。

来源

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 文档和互联网,我找不到与我的问题类似的任何内容。 非常感谢任何帮助。

【问题讨论】:

    标签: c# .net-core automapper


    【解决方案1】:

    尝试实现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 优化转换函数

    【讨论】:

    • 这也是一个有效的答案,我只是选择了更简单的解决方案,也更接近我最初的想法。
    【解决方案2】:

    除了您的示例代码中的一个错字之外,您几乎遇到了它。因为您没有在顶层进行 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()
                    );
    

    【讨论】:

      【解决方案3】:

      你错过了自动映射器的目的。

      它应该用于将一种类型的输入对象转换为不同类型的输出对象。

      您想创建一个从 MyClass 类型到 List 的映射 - 这应该被视为投影。

      您可以使用 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();
              }
          }
      

      【讨论】:

      • 虽然我一般不知道 AutoMapper 和映射的最佳实践,但直接映射到 List 使我的实现更容易。我确实明白你在说什么,感谢你的意见。
      猜你喜欢
      • 2020-12-12
      • 1970-01-01
      • 2016-01-07
      • 2017-06-11
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 2015-03-18
      相关资源
      最近更新 更多