2010-08-03 83 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