在AutoMapper中的子对象中进行不带前缀名称的展平

本文关键字:前缀 AutoMapper 对象 | 更新日期: 2023-09-27 18:29:54

将这些类视为源:

public class SourceParent
{
    public int X { get; set; }
    public SourceChild1 Child1 { get; set; }
    public SourceChild2 Child2 { get; set; }
}
public class SourceChild1
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }
}
public class SourceChild2
{
    public int I { get; set; }
    public int J { get; set; }
    public int K { get; set; }
    public int L { get; set; }
}

我正在尝试将源映射到类似于以下的目的地:

public class Destination
{
    public int X { get; set; }
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }
    public int I { get; set; }
    public int J { get; set; }
    public int K { get; set; }
    public int L { get; set; }
}

好吧,使用这个配置,可以进行映射:

Mapper.CreateMap<SourceParent, Destination>()
    .ForMember(d => d.A, opt => opt.MapFrom(s => s.Child1.A))
    .ForMember(d => d.B, opt => opt.MapFrom(s => s.Child1.B))
    .ForMember(d => d.C, opt => opt.MapFrom(s => s.Child1.C))
    .ForMember(d => d.D, opt => opt.MapFrom(s => s.Child1.D))
    .ForMember(d => d.I, opt => opt.MapFrom(s => s.Child2.I))
    .ForMember(d => d.J, opt => opt.MapFrom(s => s.Child2.J))
    .ForMember(d => d.K, opt => opt.MapFrom(s => s.Child2.K))
    .ForMember(d => d.L, opt => opt.MapFrom(s => s.Child2.L));

除此之外,当子类具有多个属性时,所有这些属性都与父类具有相同的名称,这不是一种干净的方法。

理想情况下,我想告诉AutoMapper也将Source.Child1和Source.Child2作为源,并将每个匹配的属性名称映射到目标(而不是指定每个单独的属性);像这样的东西:

Mapper.CreateMap<SourceParent, Destination>()
    .AlsoUseSource(s => s.Child1)
    .AlsoUseSource(s => s.Child2);

在AutoMapper中的子对象中进行不带前缀名称的展平

您可以使用.ConstructUsing来实现这一点。这不是世界上看起来最干净的东西,但它会起作用:

/* Map each child to the destination */
Mapper.CreateMap<SourceChild1, Destination>();
Mapper.CreateMap<SourceChild2, Destination>();
Mapper.CreateMap<SourceParent, Destination>()
    .ConstructUsing(src =>
    {
        /* Map A-D from Child1 */
        var dest = Mapper.Map<Destination>(src.Child1);
        /* Map I-L from Child2 */
        Mapper.Map(src.Child2, dest);
        return dest;
    });
/* X will be mapped automatically. */

这将成功映射所有属性。

不幸的是,对.AssertConfigurationIsValid的调用将失败,因为属性I-L将不会映射到SourceParent映射的目标类型上→Destination

当然,您可以为每个调用编写一个对.Ignore的调用,但这会破坏消除嵌套映射调用的目的。

您的另一个选择是利用这个令人敬畏的答案来忽略每个映射上的未映射属性。