14

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())たが、詳細リストがまったくコピーされません。詳細リストもディープクローン化するにはどうすればよいですか。つまり、すべてのリストアイテムを含む2つの完全に独立したオブジェクトになりますか?

更新: NHibernateでこれらのオブジェクトを使用しているため、Idプロパティを除外する必要があるため、Serializableソリューションがこれを実行するかどうかはわかりません。

UPDATE2:上記のコードを変更してIListも複製しました。NHibernateにすでに保存されていると思わせるプロパティを除外できるため、これは正常に機能しているようです。

4

2 に答える 2

9

ここにValueInjecterを使用した 1 つのソリューションがあります

        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);
        });

プライベート セッターを持つプロパティは設定されません (合理的に見え
ます) 頑張ってください ;)

編集:ここでより良い解決策を見ました

于 2010-08-03T18:17:04.427 に答える
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);
    }
}

すべての状況で機能するわけではありませんが、非常に便利です。

于 2010-08-03T13:35:50.017 に答える