简体   繁体   English

Automapper - 将简单列表映射到复杂的嵌套类型

[英]Automapper - mapping simple list to complex nested type

I have a question regarding Automapper, I have an flat list of objects that i must return in transformed DTO object to frontend, let's say, List of我有一个关于 Automapper 的问题,我有一个简单的对象列表,我必须在转换后的 DTO 对象中返回到前端,比方说,列表

List<Cars> list =
Cars
{
    public string PartCode { get; set; }
    public bool Enabled { get; set; }
    public string CarCode { get; set; }
    public int CarId { get; set; }
    public int PartId { get; set; }
}

and i need to map it to object:我需要将它映射到对象:

public class CarsDTO
{
    public int CarId;
    public string CarCode;
    public List<PartsDTO> CarParts;
}

public class PartDTO
{
    public Part Id;
    public string PartCode;
    public bool Enabled;
}

And example data:和示例数据:

part_id part_code   car_id  car_code    enabled
1   WINDOW  1   MUSTANG true
2   WHEELS  1   MUSTANG true
3   BUMPER  2   MONDEO  true
4   HOOD    2   MONDEO  false
5   WINDSHIELD  2   MONDEO  true
6   TIRE    3   KA  true
7   STEERING_WHEEL  4   FOCUS   false
8   TRANSMISSION    4   FOCUS   true

And proposed output after mapping in json:并在 json 中映射后建议输出:

"parts": [
        {
            "carId": 1,
            "carCode": "MUSTANG",
            "carParts": [
                {
                    "id": 1,
                    "partCode": "WINDOW",
                    "enabled": true
                },
                {
                    "id": 2,
                    "partCode": "WHEELS",
                    "enabled": true
                }
            ]
        },
        {
            "carId": 2,
            "carCode": "MONDEO",
            "carParts": [
                {
                    "id": 3,
                    "partCode": "BUMPER",
                    "enabled": true
                },
                {
                    "id": 4,
                    "partCode": "HOOD",
                    "enabled": false
                },
                {
                    "id": 5,
                    "partCode": "WINDSHIELD",
                    "enabled": true
                }
            ]
        },
        {
            "carId": 3,
            "carCode": "KA",
            "carParts": [
                {
                    "id": 6,
                    "partCode": "TIRE",
                    "enabled": true
                },
            ]
        },
        {
            "carId": 4,
            "carCode": "FOCUS",
            "carParts": [
                {
                    "id": 7,
                    "partCode": "STEERING_WHEEL",
                    "enabled": false
                },
                {
                    "id": 8,
                    "partCode": "TRANSMISSION",
                    "enabled": true
                ]
        }
        ]

Ive managed to map object in Linq with following query:我设法使用以下查询在 Linq 中映射对象:

    List<CarParts> carParts = new List<CarParts>();

    List<CarPartsList> list = (from t in carParts
                                 group t by new { t.CarCode, t.CarId }
                                 into grp
                                 select new CarPartsList()
                                 {
                                     GroupCode = grp.Key.CarCode,
                                     GroupId = grp.Key.CarId,
                                     GroupRights = (from
                                                    carPart in carParts
                                                    where userRight.CarCode == grp.Key.CarCode
                                                    select new Part { Id = carPart.PartId, PartCode = carPart.Code, Enabled = carPart.Enabled }).ToList()
                                 }).ToList();

But the project im working on requires Automapper to transform DTO objects, and I dont know the solution:/ Ive read the docs at: https://docs.automapper.org/en/stable/Nested-mappings.html But the example in docs is so simple that i cant make use of it.但是我正在处理的项目需要 Automapper 来转换 DTO 对象,我不知道解决方案:/我阅读了以下文档: https : //docs.automapper.org/en/stable/Nested-mappings.html但是示例中的docs 太简单了,我无法使用它。

The best answer here would be to not use AutoMapper, since in this case it will just introduce unnecessary complexity instead of simplifying your code.这里最好的答案是不使用 AutoMapper,因为在这种情况下,它只会引入不必要的复杂性,而不是简化您的代码。 The usage guidelines even state:使用指南甚至指出:

DO NOT use AutoMapper except in cases where the destination type is a flattened subset of properties of the source type除非目标类型是源类型的属性的扁平子集,否则不要使用 AutoMapper


However...然而...

If your project requires using AutoMapper here, one way would be to define a Custom Type Converter that essentially does the same LINQ projection that you would have done otherwise:如果您的项目需要在此处使用 AutoMapper,一种方法是定义一个自定义类型转换器,该转换器基本上执行与您在其他情况下所做的相同的 LINQ 投影:

public class CarPartConverter : ITypeConverter<IEnumerable<Cars>, IEnumerable<CarsDTO>>
{
    public IEnumerable<CarsDTO> Convert(IEnumerable<Cars> source, IEnumerable<CarsDTO> destination, ResolutionContext context)
    {
        return source
            .GroupBy(c => new {c.CarCode, c.CarId})
            .Select(g => new CarsDTO
            {
                CarCode = g.Key.CarCode,
                CarId = g.Key.CarId,
                CarParts = g.Select(v => new PartsDTO
                {
                    Id = v.PartId,
                    PartCode = v.PartCode,
                    Enabled = v.Enabled
                }).ToList()
            });
    }
}

Here's a complete example using that converter:这是使用该转换器的完整示例:

static void Main(string[] args)
{
    IMapper mapper = new MapperConfiguration(cfg => {
        cfg.CreateMap<IEnumerable<Cars>, IEnumerable<CarsDTO>>().ConvertUsing<CarPartConverter>();
    }).CreateMapper();

    List<Cars> cars = new List<Cars>
    {
        new Cars {PartId = 1, PartCode = "WINDOW", CarId = 1, CarCode = "MUSTANG", Enabled = true},
        new Cars {PartId = 2, PartCode = "WHEELS", CarId = 1, CarCode = "MUSTANG", Enabled = true},
        new Cars {PartId = 3, PartCode = "BUMPER", CarId = 2, CarCode = "MONDEO", Enabled = true}
    };

    IEnumerable<CarsDTO> dtos = mapper.Map<IEnumerable<CarsDTO>>(cars);

    Console.WriteLine(JsonConvert.SerializeObject(dtos, Formatting.Indented));
    Console.ReadLine();
}

Which gives the following results:这给出了以下结果:

在此处输入图片说明

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

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