如何在 Automapper 中映射嵌套对象,而不使用内联映射或多个 .ForMember?

5

有一个问题描述了我想要获取的内容,该问题链接如下:question,但是他们在使用内联映射。

源类型/目标类型

public class SrcInner
{
    public int A {get;set;} // imagine here 100500 properties
}

public class SrcOuter
{
    public int B {get;set;}
    public SrcInner C {get;set}
}

public class Dest
{
    public int A {get;set;} // so here imagine 100500 same properties, as in SrcInner
    public int B {get;set;}
}

映射配置

public static void AddMapper(this IServiceCollection services)
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<SrcInner, Dest>();
        cfg.CreateMap<SrcOuter, Dest>();
    });

    var mapper = config.CreateMapper();

    services.AddSingleton(mapper);
}

期望的行为

映射后A和B属性都被填充。

实际的行为

映射后只有B属性被填充。

重现步骤

public class Foo
{
    IMapper Mapper{get;set;}
    public Foo(IMapper mapper) // comes through dependency injection
    {
        Mapper = mapper;
    }

    public Bar()
    {
        var test = new SrcOuter()
        {
            B = 10;
            C = new SrcInner()
            {
                A = 10;
            }
        }
        var testDest = new Dest();
        mapper.Map(test, Dest);
    }
}

有没有一种适当的方式来设置配置,以便这样的映射可以工作?


更新

是否有一种将Dest映射到SrcOuter并填充SrcInner的方法?

2个回答

7

这份文档介绍了如何使用 IncludeMembers 来实现此目标,具体请参见此处

在您的情况下,配置应为:

cfg.CreateMap<SrcOuter, Dest>().IncludeMembers(s => s.C);
cfg.CreateMap<SrcInner, Dest>(MemberList.None);

如果你想双向使用这个功能,最常见的方法是在目标成员前缀加上嵌套源对象的名称,这样展平和还原操作就可以自动进行。
例如,如果你有以下对象:
public class SrcInner
{
    public int A { get; set; }
}

public class SrcOuter
{
    public int B { get; set; }
    public SrcInner Inner { get; set; }
}

public class Dest
{
    public int InnerA { get; set; }
    public int B { get; set; }
}

你不需要做任何比下面更多的配置:

cfg.CreateMap<SrcOuter, Dest>().ReverseMap();

有没有一种方法可以反过来做同样的事情,即使用填充SrcInner将Dest映射到SrcOuter? - KainWhite
根据文档,调用.ReverseMap()应该会给你那个。 - Jonas Høgh
CreateMap<A, B>.ReverseMap() 只是 CreateMap<B, A> 的语法糖,对吧? - KainWhite
你能否在你的回答中添加一些链接中重要的信息吗?链接可能会随着时间的推移失效,而这些信息对于未来的访问者解决类似问题非常重要。 - Geoff James
由于某些项目架构原因,我无法使用.ReverseMap()并重命名属性。因此,我只能使用CreateMap<Dest, SrcOuter>.ForMember(srcOuter => srcOuter.C, member => member.MapFrom(dest => dest)) - KainWhite

3

1
好的,但是想象一下,在SrcInner类中有比一个更多的属性。因此,我需要为每个这样的属性编写ForMember,这绝对不是可以接受的。 - KainWhite

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