Introduction
In most cases, no matter what area of software development you are involved in, you will need a functionality of cloning your objects. The .NET Framework provides you three ways of achieving your object copying goal:
- Implement the
ICloneable
interface, and develop cloning functionality manually for each class involved in your desired cloning.
- Serialize your object to a binary stream, and deserialize it utilizing the
BinaryFormatter
and MemoryStream
classes. In this case, your classes will need to be serializable.
- Clone using Reflection.
Sometimes, when you are working on a large project, a “stupid” deep copying would not be sufficient. Let’s say, in some cases, you need to include sub-objects, and in some of them, not. For example, let's consider these classes:
public class Person
{
private List<Person> _friends = new List<Person>();
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Person> Friends { get { return _friends; } }
public PersonManager Manager { get; set; }
}
public class PersonManager
{
private List<Person> _persons = new List<Person>();
public List<Person> Persons
{
get { return _persons; }
}
}
In some cases, when copying a single Person
, there is no need to copy the PersonManager
too. In other cases, you would like to include the Person
’s friends in the cloning, and again, in others, not. As you have already noticed, there are too many cases in this trivial example. In a real situation, they will be much more complicated.
Using the code
I suggest a declarative way of defining the cloning logic. Consider the following modification to our Person
class:
public class Person
{
private List<Person> _friends = new List<Person>();
public string Firstname { get; set; }
public string Lastname { get; set; }
[Cloneable(CloneableState.Exclude)]
[Cloneable(CloneableState.Include, "Friends")]
public List<Person> Friends { get { return _friends; } }
[Cloneable(CloneableState.Exclude)]
public PersonManager Manager { get; set; }
}
It says that, when cloning the Person
class, exclude the Manager
and Friends
objects from cloning. However, when cloning with the “Friends” flavor ([Cloneable(CloneableState.Include, "Friends")]
), copy the Person
’s friends too. The usage of this machinery is quite easy. Example:
ObjectCloner.Clone(person);
ObjectCloner.Clone(person, "Friends");
So, the first statement in the previous sample copies only Firstname
and Lastname
. The second one performs deep copy and clones the person’s friends too.
Here is the output of the demo application which is based on the sample described earlier.
Here, you can see that both copies of “De Niro” have no manager defined, and when cloning with the “Friends” flavor, the machinery performs a deep copy by filling the person’s friends.
Origin
The origin of this article can be found at C# Object Cloning Machinery.