I am trying to deep clone the following class using 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;
}
}
The Clone
method works fine for the MainData properties but seems to only do a shallow copy of the Details list. I have tried adding .ForMember(d => d.Details, o => o.UseDestinationValue())
but this does not copy the Details list at all. How can I get the Details list deep cloned as well ie, so I end up with two totally independent objects including all the list items?
UPDATE: I need to exclude the Id property as I am using these objects with NHibernate so not sure if the Serializable solution will do this.
UPDATE2: Modified the above code to clone the IList too. This seems to work fine as I can exclude properties that make NHibernate think it has already been saved.
The problem, as pointed out in the discussion of the above approach, is that AutoMapper does not do a recursive deep clone of nested objects: "...so you better make sure AutoMapper has mappings for member classes that you want to deep copy, and doesn't have mappings for member classes that you want to shallow copy."
If you have to do complex mapping behavior, it might be better to avoid using AutoMapper for that scenario. Reverse mapping can get very complicated very quickly, and unless it's very simple, you can have business logic showing up in mapping configuration.
AutoMapper is a great tool when used for simple conversions. When you start using more complex conversions, AutoMapper can be invaluable. For very simple conversions you could of course write your own conversion method, but why write something that somebody already has written?
here is one solution with the 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);
});
the properties that have private setters are not going to be set, (looks reasonable)
good luck ;)
EDIT: I did a better solution look here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With