我想在映射深层(即级别> 1)对象模型时忽略某些属性。
以下测试工作正常:
class Foo
{
public string Text { get; set; }
}
class Bar
{
public string Text { get; set; }
}
Mapper.CreateMap<Foo, Bar>()
.ForMember(x => x.Text, opts => opts.Ignore());
var foo = new Foo { Text = "foo" };
var bar = new Bar { Text = "bar" };
Mapper.Map(foo, bar);
Assert.AreEqual("bar", bar.Text);
但是,当我尝试执行相同的映射但将 Foo 和 Bar 作为父类的属性时,以下测试失败:
class ParentFoo
{
public Foo Child { get; set; }
}
class ParentBar
{
public Bar Child { get; set; }
}
Mapper.CreateMap<ParentFoo, ParentBar>();
Mapper.CreateMap<Foo, Bar>()
.ForMember(x => x.Text, opts => opts.Ignore());
var parentFoo = new ParentFoo
{
Child = new Foo { Text = "foo" }
};
var parentBar = new ParentBar
{
Child = new Bar { Text = "bar" }
};
Mapper.Map(parentFoo, parentBar);
Assert.AreEqual("bar", parentBar.Child.Text);
自动映射器不会忽略 Child 类的文本(即将其保留为“bar”),而是将值设置为 null。我的映射配置出了什么问题?
Automapper 有两种方法可以执行映射。第一种方法是简单地将源对象提供给 Automapper,它将创建一个新的目标对象并为您填充所有内容。这是大多数应用程序使用 Automapper 的方式。但是,第二种方法是为其提供源和现有目标,Automapper 将使用您的映射更新现有目标。
在第一个示例中,您为其提供了一个现有的目标值,以便 Automapper 将使用该值。在第二个示例中,Automapper 将为 ParentFoo 和 ParentBar 进行映射,但是当它到达 Child 时,它将创建一个新的 Child,然后进行映射(这是默认行为)。这会导致 Text 属性为 null。如果您想使用现有的 Child 对象,则需要配置 Automapper 以使用 UseDestinationValue 来执行此操作:
Mapper.CreateMap<ParentFoo, ParentBar>()
.ForMember(b => b.Child, o => o.UseDestinationValue());
这会让你的测试通过(只要你在设置parentBar.Child.Text时去掉第一个空格!)。