2011-03-23 279 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