如何使用AutoMapper深度克隆包含IList属性的对象

Pie*_*ers 13 c# clone list automapper valueinjecter

我正在尝试使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Clone方法适用于MainData属性,但似乎只执行详细信息列表的浅表副本.我尝试过添加,.ForMember(d => d.Details, o => o.UseDestinationValue())但这根本不会复制详细信息列表.如何才能获得深度克隆的详细信息列表,因此我最终得到两个完全独立的对象,包括所有列表项?

更新:我需要排除Id属性,因为我在NHibernate中使用这些对象,所以不确定Serializable解决方案是否会这样做.

UPDATE2:修改了上面的代码来克隆IList.这似乎工作正常,因为我可以排除使NHibernate认为它已被保存的属性.

Jim*_*ard 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它并不适用于所有情况,但它非常方便.


Omu*_*Omu 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);
        });
Run Code Online (Sandbox Code Playgroud)

不会设置具有私有设置器的属性,(看起来合理)
祝你好运;)

编辑:我在这里做了更好的解决方案