Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep Copy of Complex Third Party Objects/Classes [duplicate]

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:

  • Manually, Property by Painstaking Property: I attempted this with the first of 7 field objects (PDFTextBoxField), but it quickly got out of hand with the multitude properties that are also different types of classes. In the end, I still had lingering references to the original object where it a shallow copy was created instead of a deep copy as intended.
  • Serialization: The classes are not marked as Serializable, nor will the vendor change this. I asked them to and they said no.
  • ICloneable: Would need to be implemented by the vendor.
  • AutoMapper: This seems to be for copying data from one or more object types into another object type. The objects I'm working with are the same type. Though I'm not opposed to using this if it is the best solution.
  • Emit Mapper: This project appears to have been abandoned.
  • MemberwiseClone: Does a shallow copy, not the deep copy I'm looking for, though this is suggested on a ton of other posts when the questioner specifically requests a deep copy.
  • Value Injecter: I implemented FastDeepCloneInjection from ValueInjecter on CodePlex but the majority of the classes that need to be injected from do not have a 0 parameter constructor which is required when creating a new instance for the copy. ValueInjecter doesn't allow skipping of certain properties, or I would just skip the items with no default constructor and leave them set to null (the default). I ran into this right away with the very first class. To attempt to get around the issue, I created a wrapper class inherited from the original and cast the original into the wrapper (and vice versa on return), but I don't think that's a good solution.

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.

like image 252
mslissap Avatar asked Feb 25 '15 21:02

mslissap


People also ask

What is the most efficient way to deep clone an object in JavaScript?

Using the Json. Among the above mentioned three ways, for an object to be deep cloned, JSON. stringify() and JSON. parse() functions are used. The parse() method accepts a JSON String as a parameter and creates a JavaScript object accordingly.

How can you actually the deep cloning of an object?

To achieve a deep copy, we can serialize an object and then deserialize it to a new object.

What is object cloning explain deep copy and shallow copy with examples?

In object-oriented programming, object copying is creating a copy of an existing object, the resulting object is called an object copy or simply copy of the original object. There are several ways to copy an object, most commonly by a copy constructor or cloning. We can define Cloning as “create a copy of object”.


1 Answers

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);
}
like image 172
wal Avatar answered Oct 02 '22 17:10

wal