2010-08-03 107 views
13

我想深克隆使用AutoMapper下面的類一個IList屬性深克隆對象:如何包含使用AutoMapper

public class MainData 
{ 
    public MainData() 
    { 
     Details = new List<Detail>(); 
    } 

    public int Id { get; private set; } 
    public DateTime LastUpdate { get; private set; } 
    public IList<Detail> Details { get; private set; } 
    public int Prop1 { get; set; } 
    public int Prop2 { get; set; } 

    public void AddDetail(Detail detail) 
    { 
     Details.Add(detail); 
    } 

    public void RemoveDetail(Detail detail) 
    { 
     Details.Remove(detail); 
    } 

    public MainData Clone() 
    { 
     Mapper.Reset(); 
     Mapper.CreateMap<MainData, MainData>().ForMember(d => d.Id, o => o.Ignore()); 
     // Mapper.CreateMap<Detail, Detail>().ForMember(d => d.Id, o => o.Ignore()); // REMOVED 
     var newMainData = new MainData(); 
     Mapper.Map(this, newMainData); 
     newMainData.Details = this.Details.Select(item => item.Clone()).ToList(); // ADDED 
     return newMainData; 
    } 
} 

public class Detail 
{ 
    public int Id { get; private set; } 
    public string Name { get; set; } 
    public double Area { get; set; } 
    public double Height { get; set; } 

    public Detail Clone() // ADDED 
    { 
     Mapper.CreateMap<Detail, Detail>().ForMember(d => d.Id, o => o.Ignore()); 
     var newDetail = new Detail(); 
     Mapper.Map(this, newDetail); 
     return newDetail; 
    } 
} 

Clone方法工作正常的MainData性質,但似乎只能做一個淺拷貝的詳細信息列表。我曾嘗試添加.ForMember(d => d.Details, o => o.UseDestinationValue()),但這並未完全複製「詳細信息」列表。我怎樣才能深入克隆詳細列表,也就是說,所以我最終得到兩個完全獨立的對象,包括所有列表項目?

UPDATE:我需要排除Id屬性,因爲我在NHibernate中使用這些對象,所以不確定Serializable解決方案是否會執行此操作。

UPDATE2:修改了上面的代碼來克隆IList。這似乎工作正常,因爲我可以排除使NHibernate認爲它已被保存的屬性。

回答

9

這裏是一個解決方案與ValueInjecter

 var clone = new MainData(); 

     clone.InjectFrom(mainData);//mainData is your source 

     mainData.Details.AsParallel.ForAll(detail => 
     { 
      var dc = new Detail(); 
      dc.InjectFrom(detail); 
      clone.AddDetail(dc); 
     }); 

有私有制定者都不會設置的屬性,(貌似合理的)
好運;)

編輯: 我做更好的解決方案看看here

+0

非常好的庫,效果很好。不得不將PLINQ部分更改爲ForEach循環,因爲我還沒有使用.NET 4。 – 2010-08-04 00:41:25

+0

@Piers邁爾斯,我做了一些更通用的克隆,你可以在這裏看到http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu 2011-02-08 08:14:17

+0

感謝您的更新,我會檢查出來。 – 2011-02-08 09:03:51

9

AutoMapper實際上並不是一個克隆API。我會使用這種克隆技巧:

public static object CloneObject(object obj) 
{ 
    using (MemoryStream memStream = new MemoryStream()) 
    { 
     BinaryFormatter binaryFormatter = new BinaryFormatter(null, 
      new StreamingContext(StreamingContextStates.Clone)); 
     binaryFormatter.Serialize(memStream, obj); 
     memStream.Seek(0, SeekOrigin.Begin); 
     return binaryFormatter.Deserialize(memStream); 
    } 
} 

它不適用於所有情況,但它非常方便。

+0

謝謝,我在我的搜索中遇到了幾次這個解決方案,但不確定我想讓所有的類都可以Serializable。 Automapper方法看起來非常優雅,如果我可以讓它按我的需要工作。 – 2010-08-03 13:42:18

+0

這是一個受歡迎的克隆黑客。不幸的是它引入了序列化/反序列化帶來的各種問題。我希望AutoMapper也會更直接:) – 2017-12-07 19:42:46