2011-03-23 325 views
7

我想在映射深层(即层次> 1)对象模型时忽略某些属性。Automapper忽略属性忽略

下面的测试工作正常:

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和酒吧的性质上的父类中的下列测试失败:

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”)automapper将该值设置为null。我的映射配置有什么问题?

回答

9

Automapper有两种方法可以执行映射。第一种方法是简单地为Automapper提供源对象,它将创建一个新的目标对象并为您填充所有内容。这是大多数应用程序使用Automapper的方式。但是,第二种方法是同时给它一个源和一个现有目标,Automapper将用你的映射更新现有的目标。

在第一个示例中,您要给它一个现有的目标值,以便Automapper将使用它。在第二个示例中,Automapper将为ParentFoo和ParentBar执行映射,但是当它到达Child时,它将创建一个新的Child,然后执行映射(这是默认行为)。这导致Text属性为空。如果要使用现有的子对象,你需要配置Automapper这样做与UseDestinationValue:

Mapper.CreateMap<ParentFoo, ParentBar>() 
    .ForMember(b => b.Child, o => o.UseDestinationValue()); 

这使得测试合格(只要设置parentBar当你摆脱第一空间.Child.Text!)。

+0

谢谢帕特里克。完善!我只是在目标集合的上下文中考虑了UseDestinationValue,但现在这一切都合情合理。 – Brownie 2011-03-23 22:21:20