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

Automapper - mapping simple list to complex nested type

我有一个关于 Automapper 的问题, 我有一个简单的对象列表,我必须 return 在转换后的 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; }
}

我需要将它映射到对象:

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

和示例数据:

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

并在 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
                ]
        }
        ]

我已经使用以下查询在 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();

但是我正在处理的项目需要 Automapper 来转换 DTO 对象,我不知道解决方案:/我已经阅读了以下文档: https://docs.automapper.org/en/stable/Nested-mappings.html 但是文档里的例子太简单了,我不会用。

这里最好的答案是不要使用 AutoMapper,因为在这种情况下它只会引入不必要的复杂性而不是简化代码。 usage guidelines偶数状态:

DO NOT use AutoMapper except in cases where the destination type is a flattened subset of properties of the source type


然而...

如果您的项目需要 在此处使用 AutoMapper,一种方法是定义一个 Custom Type Converter,它基本上执行与其他方式相同的 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()
            });
    }
}

下面是使用该转换器的完整示例:

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

给出以下结果: