首页 > 解决方案 > AutoMapper 不同级别

问题描述

尝试从 Customer 映射到 CustomerDto 但在源中的那个额外层有问题(我无法控制源,所以很遗憾我无法对齐两者)。

public class Customer
{
    public string Name { get; set; }
    public AddressSet AddressSet { get; set; }
}

public class AddressSet
{
    public AddressSetResults[] AddressSetResults { get; set; }    
}

public class AddressSetResults
{
    public string Street { get; set; }
    public string HouseNumber { get; set; }
}

public class CustomerDto
{
    public string Name { get; set; }
    public AddressDto AddressDto { get; set; }
}

public class AddressDto
{
    public string Street { get; set; }
    public string HouseNumber { get; set; }
}

以下不适用于AddressDto,知道我缺少什么吗?

CreateMap<Customer, CustomerDto>()
 .ForMember(dest => dest.AddressDto , opt => opt.MapFrom(src => src.AddressSet.AddressSetResults))

标签: automapper

解决方案


两件事情:

1) 缺少从 AddressSetResults 到 AddressDto 的映射

为了映射内部地址,您还需要为这些内部类型创建映射:

CreateMap<AddressSetResults, AddressDto>();

2) 从 AddressSetResults 数组的元素映射,而不是从数组本身映射

这种方法:

.ForMember(
    dest => dest.AddressDto, 
    opt => opt.MapFrom(src => src.AddressSet.AddressSetResults))

告诉 AutoMapper 映射到AddressDto哪个AddressSetResultsAddressSetResults. 这是不正确的,因为 AutoMapper 不知道如何从元素数组映射到一个元素。除非您也为此创建地图,否则这不是一个好的解决方案。

假设AddressSetResults最多包含一个地址,您可以解决FirstOrDefault()在映射表达式末尾再添加一个调用的问题:

.ForMember(
    dest => dest.AddressDto, 
    opt => opt.MapFrom(src => src.AddressSet.AddressSetResults.FirstOrDefault()))

FirstOrDefault()需要System.Linq命名空间。

为什么不只是First()?如果源AddressSetResults数组不包含任何元素,则映射将失败并导致异常,因为找不到满足First()方法调用的元素。使其抵抗无元素场景FirstOrDefault()是更安全的解决方案。


最终的工作配置:

CreateMap<Customer, CustomerDto>()
    .ForMember(
        dest => dest.AddressDto,
        opt => opt.MapFrom(src => src.AddressSet.AddressSetResults.FirstOrDefault()));
CreateMap<AddressSetResults, AddressDto>();

推荐阅读