This post relates how to Copy/Clone custom object in C# (Deep and Shallow Clone).
In this example I will be having a base class that all my custom object will be inheriting from.
Updates: After quiet some research on the subject i recently found some interesting articles on this subject and wanted to share them on this post.
Object Cloning Using IL in C#
This subject is inspired on a session I followed on the TechDays 2008, that addressed the fact that IL (Intermediate Language) can be used to clone objects, among other things, and that it’s not evil at all, and it can be pretty performant also.
You only have to see that you don’t overuse it tho, because otherwise the readability of your code is reduced, which is not a good thing for the maintenance. And wrong usage of reflection (what IL is, or at least uses) can also result in poor performance.
Read more: http://whizzodev.blogspot.com/2008/03/object-cloning-using-il-in-c.html
C# Class For Making a Deep Copy Clone of an Arbitrary Object
Here is a C# class that can create a deep copy clone of an arbitrary object. The thing that’s special about it is that it should work for any class that extends it, so that you don’t need to re-write a custom clone() function for every child class (as it seems the C# framework creators would like). This does a deep copy so be careful about members that recursively include one another.
Another way of doing this would be to use serialization . . . I just personally thought the reflection package would be more elegant.
Read more: http://www.thomashapp.com/node/106
C# Object Clone Wars
Cloning C# objects is one of those things that appears easy but is actually quite complicated with many “gotchas.” This article describes the most common ways to clone a C# object.
Shallow vs. Deep Cloning
There are two types of object cloning: shallow and deep. A shallow clone copies the references but not the referenced objects. A deep clone copies the referenced objects as well.
Clone C# Object using Serialization and De-serialization (Deep Clone)
In this example i’ll be using Serialization and De-Serialization to make a deep clone of the Person Class.
You must import the following namespaces to start with.
1
2
3
4
5
6
|
using
System;
using
System.Text;
using
System.Xml;
using
System.Xml.Serialization;
using
System.Runtime.Serialization;
using
System.IO;
|
Let’s create a base class Person that all our other classes with inherit from. It will contain the following methods:
- ToXMLString() : Returns an XML version of the current object
- Deserialize(XmlDocument xml, Type type) : De-serialize the current XMLDocument cast it to the current type
- Serialize(object o) : Serialize the current object and outputs an XMLDocument
- Clone(): Runs a Serialization and De-serialization and returns a clone of the current Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
[Serializable()]
public
abstract
class
Person
{
/// <summary>
/// To XML string.
/// </summary>
/// <returns></returns>
public
string
ToXMLString()
{
XmlSerializer serializer =
new
XmlSerializer(
this
.GetType());
MemoryStream dataStream =
new
MemoryStream();
XmlTextWriter writer =
new
XmlTextWriter(dataStream, Encoding.UTF8);
serializer.Serialize(dataStream,
this
);
return
writer.ToString();
}
/// <summary>
/// Deserializes an xml document back into an object
/// </summary>
/// <param name="xml">The xml data to deserialize</param>
/// <param name="type">The type of the object being deserialized</param>
/// <returns>A deserialized object</returns>
public
static
object
Deserialize(XmlDocument xml, Type type)
{
XmlSerializer s =
new
XmlSerializer(type);
string
xmlString = xml.OuterXml.ToString();
byte
[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlString);
MemoryStream ms =
new
MemoryStream(buffer);
XmlReader reader =
new
XmlTextReader(ms);
Exception caught =
null
;
try
{
object
o = s.Deserialize(reader);
return
o;
}
catch
(Exception e)
{
caught = e;
}
finally
{
reader.Close();
if
(caught !=
null
)
throw
caught;
}
return
null
;
}
/// <summary>
/// Serializes an object into an Xml Document
/// </summary>
/// <param name="o">The object to serialize</param>
/// <returns>An Xml Document consisting of said object's data</returns>
public
static
XmlDocument Serialize(
object
o)
{
XmlSerializer s =
new
XmlSerializer(o.GetType());
MemoryStream ms =
new
MemoryStream();
XmlTextWriter writer =
new
XmlTextWriter(ms,
new
UTF8Encoding());
writer.Formatting = Formatting.Indented;
writer.IndentChar =
' '
;
writer.Indentation = 5;
Exception caught =
null
;
try
{
s.Serialize(writer, o);
XmlDocument xml =
new
XmlDocument();
string
xmlString = ASCIIEncoding.UTF8.GetString(ms.ToArray());
xml.LoadXml(xmlString);
return
xml;
}
catch
(Exception e)
{
caught = e;
}
finally
{
writer.Close();
ms.Close();
if
(caught !=
null
)
throw
caught;
}
return
null
;
}
/// <summary>
/// Creates a new object that is a copy of the current instance.
/// </summary>
/// <returns>
/// A new object that is a copy of this instance.
/// </returns>
public
object
Clone()
{
return
Deserialize(Serialize(
this
),
this
.GetType());
}
}
|
Here are sample classes that herits from the abstract base class and clone operation are performed upon them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public
class
Clerk: Person
{
private
string
position;
/// <summary>
/// Gets or sets the position.
/// </summary>
/// <value>The position.</value>
public
string
Position
{
get
{
return
position; }
set
{ position = value; }
}
}
public
class
Developer: Person
{
private
string
skill;
/// <summary>
/// Gets or sets the skill.
/// </summary>
/// <value>The skill.</value>
public
string
Skill
{
get
{
return
skill; }
set
{ skill= value; }
}
}
|
Using clone method.
1
2
3
4
5
6
7
8
9
10
|
public
void
UpdateSkills()
{
IList<clerk> clerkList =
new
ArrayList();
IList<clerk> newClerkList =
new
ArrayList();
foreach
(Clerk clerk
in
clerkList)
{
newClerkList.Add((Clerk)clerk.Clone());
}
}
|
from: http://www.wacdesigns.com/2008/08/05/copy-clone-custom-object-in-c/