2017-08-01 44 views
1

我有2個類,Class1應該映射到Class2。我使用AutoMapper進行測繪。我想測試我的配置映射器,爲此我使用AutoFixture。源類Class1的屬性類型爲IList <>,目標類Class2具有類似的屬性,但類型爲IEnumerable <>。爲了簡化測試準備,我使用AutoFixture(使用AutoMoqCustomization)來初始化源對象和目標對象。但在使用AutoFixture初始化IEnumerable類型的屬性後,AutoMapper無法映射屬性。AutoMapper和AutoFixture中的衝突

錯誤文本:

錯誤映射類型。

映射類型:1類 - >類2 ConsoleApplication1.Class1 - > ConsoleApplication1.Class2

類型地圖配置:1類 - >類2 ConsoleApplication1.Class1 - > ConsoleApplication1.Class2

房產:項目

任何人都可以幫助我配置AutoMapper或AutoFixture使映射工作?作爲一種解決方法,我可以將null分配給目標屬性,但我不想在每個測試中執行此操作。代碼

簡單的例子:

public class AutoMapperTests 
{ 
    public static void TestCollectionsProperty() 
    { 
     Mapper.Initialize(cfg => 
     { 
      cfg.CreateMap<ItemClass1, ItemClass2>(); 
      cfg.CreateMap<Class1, Class2>(); 
     }); 

     var src = new Class1(); 
     src.Items = new List<ItemClass1>() 
     { 
      new ItemClass1() { Text = "111" }, 
      new ItemClass1() { Text = "222" } 
     }; 

     var fixture = new Fixture(); 
     var dst = fixture.Create<Class2>(); 

     Mapper.Map(src, dst); //Error at this line of code 
    } 
} 

public class Class1 
{ 
    public IList<ItemClass1> Items { get; set; } 
} 

public class Class2 
{ 
    public IEnumerable<ItemClass2> Items { get; set; } 
} 

public class ItemClass1 
{ 
    public string Text { get; set; } 
} 
public class ItemClass2 
{ 
    public string Text { get; set; } 
} 
+1

發佈的代碼無法編譯,因爲(AFICT)'Mapper.CreateMap'已被棄用並從AutoMapper中移除。請更新repro代碼,或發佈使用中的NuGet包列表,包括其版本號。 –

+0

謝謝你的評論,我已經更新了示例 –

回答

0

這裏是你的問題的工作示例。正如@Mark Seemann所說的,Mapper.CreateMap已被棄用,所以這個例子使用了新的結構。

Mapper.Initialize(cfg => 
{ 
    cfg.CreateMap<ItemClass1, ItemClass2>(); 
    cfg.CreateMap<Class1, Class2>(); 
}); 

var src = new Class1(); 
src.Items = new List<ItemClass1>() 
{ 
    new ItemClass1() { Text = "111" }, 
    new ItemClass1() { Text = "222" } 
}; 

var dest = Mapper.Map<Class1, Class2>(src); 
+0

謝謝你的回答,但問題是我需要使用void方法Mapper.Map (src,dst);它不起作用。當我使用返回目標對象的方法時,即使使用舊版本的AutoMapper,其中CreateMap是Mapper類的靜態方法,所有東西都可以正常工作。 –

1

它本身並不是一個真正的AutoFixture問題。

var dst = new Class2(); 
dst.Items = Enumerable.Range(0, 1).Select(_ => new ItemClass2()); 

這將產生類似的錯誤消息:

無法轉換類型的對象「WhereSelectEnumerableIterator 2[System.Int32,Ploeh.StackOverflow.Q45437098.ItemClass2]' to type 'System.Collections.Generic.IList 1 [Ploeh.StackOverflow.Q45437098您可以通過,而不是創建dst這樣重現它沒有AutoFixture .ItemClass2]'

這應該是不言自明的:WhereSelectEnumerableIterator<int, ItemClass2>不執行IList<ItemClass2>。 AutoMapper嘗試進行該轉換,並失敗。

最簡單的解決方法是可能避免填充dst

var dst = new Class2(); 

如果必須使用AutoFixture對於這一點,你可以做這樣的:

var dst = fixture.Build<Class2>().OmitAutoProperties().Create(); 

除非Class2構造函數一些複雜的,但是,我沒有看到在這種情況下使用AutoFixture的重點。

另一方面,如果您確實需要填入dst,您只需確保dst.Items可轉換爲IList<ItemClass2>。要做到這一點的一種方法是這樣的:

var dst = fixture.Create<Class2>(); 
dst.Items = dst.Items.ToList(); 

您可以創建一個自定義,以確保自動發生這種情況,但如果你需要與幫助,請提出新問題(如果你沒有找到一個已經回答了這個問題)。

0

AM需要IList,因爲您正在映射到現有列表並且通過調用IList.Add來工作。