【问题标题】:Automapper - mapping simple list to complex nested typeAutomapper - 将简单列表映射到复杂的嵌套类型
【发布时间】:2019-12-13 03:57:40
【问题描述】:

我有一个关于 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; }
}

我需要将它映射到对象:

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 但是文档中的示例太简单了,我无法使用它。

【问题讨论】:

    标签: c# linq nested automapper


    【解决方案1】:

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

    不要使用 AutoMapper,除非目标类型是 源类型属性的扁平子集


    不过……

    如果您的项目需要在此处使用 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();
    }
    

    结果如下:

    【讨论】:

    • 太好了,这也是我的想法:不要使用 automapper,尤其是因为 user2829330 已经有了一个可行的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 2019-04-26
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多