2015-08-14 107 views
1

我有兩個類。一個是名爲「ImportedContact」的類,它映射到csv文件中的記錄。對於文件中的每一行,都有這個類的實例。我們使用LINQtoCSV庫來檢索這個類的值。第二個是與Telerik的DataAccess ORM庫一起使用的名爲「Contact」的類。因此,我們的過程是使用LINQtoCSV讀取csv文件,填充ImportedContact類實例並將它們分別映射到Contact類實例中,在那裏將它們添加到數據庫上下文並更新數據庫。當我們在這些類之間映射時,我會得到一個對我來說沒有意義的異常。AutoMapper 4映射錯誤

這裏是ImportedContact類:

using System; 
using System.Linq; 
using LINQtoCSV; 

namespace SharePointDirectory.Jobs 
{ 
    public class ImportedContact 
    { 
     [CsvColumn(Name = "Location Name", FieldIndex = 4)] 
     public string BranchId 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Work Wireless", FieldIndex = 7)] 
     public string CellNumber 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Home Department Name", FieldIndex = 3)] 
     public string Dept 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Extension", FieldIndex = 9)] 
     public string Ext 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "First Name", FieldIndex = 2)] 
     public string FirstName 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Last Name", FieldIndex = 1)] 
     public string LastName 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Shift -- Value", FieldIndex = 5)] 
     public string Shift 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Job Title", FieldIndex = 8)] 
     public string Title 
     { 
      get; 
      set; 
     } 

     [CsvColumn(Name = "Work Phone", FieldIndex = 6)] 
     public string WorkNumber 
     { 
      get; 
      set; 
     } 
    } 
} 

這裏是Contact類:

using System; 
using System.Linq; 
using System.Runtime.Serialization; 

namespace SharePointDirectory.Data 
{ 
    [Serializable] 
    public class Contact : ISerializable 
    { 
     public Contact() 
     { 
     } 

     protected Contact(SerializationInfo info, StreamingContext context) 
     { 
      this.Id = info.GetInt64("Id"); 
      this.EmployeeId = (int?)info.GetValue("EmployeeId", typeof(int?)); 
      this.FirstName = info.GetString("FirstName"); 
      this.LastName = info.GetString("LastName"); 
      this.Title = info.GetString("Title"); 
      this.Ext = info.GetString("Ext"); 
      this.Dept = info.GetString("Dept"); 
      this.DeptId = info.GetString("DeptId"); 
      this.CellNumber = info.GetString("CellNumber"); 
      this.PhotoPath = info.GetString("PhotoPath"); 
      this.Active = info.GetBoolean("Active"); 
      this.Office = info.GetBoolean("Office"); 
      this.Shift = info.GetString("Shift"); 
      this.BranchId = info.GetString("BranchId"); 
      this.WorkNumber = info.GetString("WorkNumber"); 
     } 

     public bool Active 
     { 
      get; 
      set; 
     } 

     public string BranchId 
     { 
      get; 
      set; 
     } 

     public string CellNumber 
     { 
      get; 
      set; 
     } 

     public string Dept 
     { 
      get; 
      set; 
     } 

     public string DeptId 
     { 
      get; 
      set; 
     } 

     public int? EmployeeId 
     { 
      get; 
      set; 
     } 

     public string Ext 
     { 
      get; 
      set; 
     } 

     public string FirstName 
     { 
      get; 
      set; 
     } 

     public long Id 
     { 
      get; 
      set; 
     } 

     public string LastName 
     { 
      get; 
      set; 
     } 

     public bool Office 
     { 
      get; 
      set; 
     } 

     public string PhotoPath 
     { 
      get; 
      set; 
     } 

     public string Shift 
     { 
      get; 
      set; 
     } 

     public string Title 
     { 
      get; 
      set; 
     } 

     public string WorkNumber 
     { 
      get; 
      set; 
     } 

     public void GetObjectData(SerializationInfo info, StreamingContext context) 
     { 
      info.AddValue("Id", this.Id, typeof(long)); 
      info.AddValue("EmployeeId", this.EmployeeId, typeof(int?)); 
      info.AddValue("FirstName", this.FirstName, typeof(string)); 
      info.AddValue("LastName", this.LastName, typeof(string)); 
      info.AddValue("Title", this.Title, typeof(string)); 
      info.AddValue("Ext", this.Ext, typeof(string)); 
      info.AddValue("Dept", this.Dept, typeof(string)); 
      info.AddValue("DeptId", this.DeptId, typeof(string)); 
      info.AddValue("CellNumber", this.CellNumber, typeof(string)); 
      info.AddValue("PhotoPath", this.PhotoPath, typeof(string)); 
      info.AddValue("Active", this.Active, typeof(bool)); 
      info.AddValue("Office", this.Office, typeof(bool)); 
      info.AddValue("Shift", this.Shift, typeof(string)); 
      info.AddValue("BranchId", this.BranchId, typeof(string)); 
      info.AddValue("WorkNumber", this.WorkNumber, typeof(string)); 
     } 
    } 
} 

這裏是設置我們如何映射:

Mapper.Initialize(configuration => configuration.CreateMap<ImportedContact, Contact>()); 

下面是我們如何執行運行時的實際地圖:

var contact = Mapper.Map<Contact>(importedContact); 

當我們執行的地圖,這是我們所看到的異常消息:

{ 
    "Missing type map configuration or unsupported mapping. 

    Mapping types: 
    ImportedContact -> SerializationInfo 
    SharePointDirectory.Jobs.ImportedContact -> System.Runtime.Serialization.SerializationInfo 

    Destination path: 
    Contact 

    Source value: 
    SharePointDirectory.Jobs.ImportedContact" 
} 

System.Exception {AutoMapper.AutoMapperMappingException} 

我不明白爲什麼它試圖在那裏列出這兩種類型進行映射。 SerializationInfo是其中一個構造函數的構造函數參數,但也有一個無參數構造函數,我覺得它應該注意,而不是相反。這個相同的代碼似乎在AutoMapper 3.3版本中工作正常。

我一直在查看AutoMapper文檔,看看能否找到任何東西。迄今爲止最接近的是它提到了這兩件事。

https://github.com/AutoMapper/AutoMapper/wiki/Construction

https://github.com/AutoMapper/AutoMapper/wiki/Configuration

具體有關配置前綴聲明:

By default AutoMapper recognizes the prefix "Get" 

回答

1

我也有類似的問題,即AutoMapper決定使用與參數,而不是默認的構造函數的構造。

我的解決方法是實例化目標對象自己做出AutoMapper填寫屬性:

var contact = new Contact(); 
Mapper.Map(importedContact, contact); 
+0

我的示例顯示了導致問題的兩種特定類型。但實際上代碼是用泛代碼編寫的。所以我們一直依靠Automapper來執行Td類型的對象實例化。我們不得不重構代碼來做我們自己的Activator.CreateInstance來調用它。我很希望有一些東西可以在映射配置中表達出來,而不是隻能在API中調用特定的Map方法。 – Ristogod

+0

我明白了。我認爲行爲在更新版本的AutoMapper中發生了變化,因爲我在通過NuGet升級後出現了錯誤。我不知道是否有配置,對不起。我會讓我的答案留下來,因爲它可能對其他人有用。 –

0

我不知道永遠版本自動映射器,但我想,你還是需要指定目的地映射類,否則它不知道在哪裏映射。

var contact = Mapper.Map<ImportedContact, Contact>(importedContact); 
+0

Automapper不需要申報兩種類型。它可以確定通過參數暗示的源類型。目標類型通過通用聲明給出。 Automapper在版本3中支持這種語法/ api。 – Ristogod