I'm have been working on a project to create PDF forms using PDFView4Net. While the library is generally good, the forms creator is primitive and lacking basic features (such as copy/paste, alignment, formatting, etc.) when working with form fields (i.e. text boxes, check boxes, etc.).
The problem: I have been extending the functionality for field objects and getting tripped up on copy/paste. To do this, I need a deep copy of the object with no references to the original whatsoever. I emailed the vendor, requesting information about their recommended method for copying these objects, to which they replied I needed make a copy of each property by hand, manually ... beats head on desk. These are large classes, with multiple embedded classes as properties, as well as UI elements.
The question: Are there any good methods out there that perform a deep copy for complex objects that don't require serialization, doesn't require access to or changes to the source classes and doesn't require a default constructor?
What I have tried/reviewed: I have researched various ways to make a deep copy of an object and discarded them one by one:
Edit: I really do not feel this question is a duplicate. I've searched extensively for a solution, including the post marked as the duplicate/original, and was unable to find a satisfactory resolution. As stated, I don't have access to change the classes that I need to copy. This discounts DataContractSerializer, BinaryFormatter, and any other type of serialization. This also discounts the reflection examples I've seen using Activator.CreateInstance, as about 95% of the classes I need to copy don't have a constructor that takes 0 arguments. This is the same issue I ran into using ValueInjecter. This also discounts using ICloneable.
I would use AutoMapper for this. Consider the following class definition: (note private ctor)
public class Parent
{
public string Field1 { get; set; }
public Level1 Level1 { get; set; }
public static Parent GetInstance()
{
return new Parent() { Field1 = "1", Level1 = new Level1 { Field2 = "2", Level2 = new Level2() { Field3 = "3"}}};
}
private Parent() { }
}
public class Level1
{
public string Field2 { get; set; }
public Level2 Level2 { get; set; }
}
public class Level2
{
public string Field3 { get; set; }
}
You can then setup AutoMapper to deep clone as required:
[TestMethod]
public void DeepCloneParent()
{
Mapper.CreateMap<Parent, Parent>();
Mapper.CreateMap<Level1, Level1>();
Mapper.CreateMap<Level2, Level2>();
var parent = Parent.GetInstance();
var copy = Mapper.Map<Parent, Parent>(parent);
Assert.IsFalse(copy == parent);//diff object
Assert.IsFalse(copy.Level1 == parent.Level1);//diff object
Assert.IsFalse(copy.Level1.Level2 == parent.Level1.Level2);//diff object
Assert.AreEqual("1", copy.Field1);
Assert.AreEqual("2", copy.Level1.Field2);
Assert.AreEqual("3", copy.Level1.Level2.Field3);
}