AutoMapper中子对象没有前缀名称的展平

5

考虑这些类作为源代码:

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);
1个回答

3
你可以使用.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将不会在从SourceParentDestination的映射的目标类型上映射。

当然,你可以为每个属性编写一个.Ignore调用,但这有点违背了摆脱嵌套映射调用的目的。

您的另一个选择是利用这个很棒的答案来忽略每个映射中未映射的属性。


谢谢,这很有用。实际上,我最终做了类似的事情(使用 AfterMap 来完成相同的工作)。但我会再等一两天,看是否有人提供一个更“简洁”的答案。 - Iravanchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接