Given the following class:
class A
{
public List ListB;
// etc...
}
where B
is another class that may inheri
Try using a memory stream to get a deep copy of your object:
public static T MyDeepCopy<T>(this T source)
{
try
{
//Throw if passed object has nothing
if (source == null) { throw new Exception("Null Object cannot be cloned"); }
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
//variable declaration
T copy;
var obj = new DataContractSerializer(typeof(T));
using (var memStream = new MemoryStream())
{
obj.WriteObject(memStream, source);
memStream.Seek(0, SeekOrigin.Begin);
copy = (T)obj.ReadObject(memStream);
}
return copy;
}
catch (Exception)
{
throw;
}
}
Here is more.
private interface IDeepCopy<T> where T : class
{
T DeepCopy();
}
private class MyClass : IDeepCopy<MyClass>
{
public MyClass DeepCopy()
{
return (MyClass)this.MemberwiseClone();
}
}
Pluss: Yoy can control copy process (if your class has identifier property you can set them, or you can write other business logic code)
Minus: class can be marked as sealed
You can try this. It works for me
public static object DeepCopy(object obj)
{
if (obj == null)
return null;
Type type = obj.GetType();
if (type.IsValueType || type == typeof(string))
{
return obj;
}
else if (type.IsArray)
{
Type elementType = Type.GetType(
type.FullName.Replace("[]", string.Empty));
var array = obj as Array;
Array copied = Array.CreateInstance(elementType, array.Length);
for (int i = 0; i < array.Length; i++)
{
copied.SetValue(DeepCopy(array.GetValue(i)), i);
}
return Convert.ChangeType(copied, obj.GetType());
}
else if (type.IsClass)
{
object toret = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
object fieldValue = field.GetValue(obj);
if (fieldValue == null)
continue;
field.SetValue(toret, DeepCopy(fieldValue));
}
return toret;
}
else
throw new ArgumentException("Unknown type");
}
Thanks to DetoX83 article on code project.
Can't you do this?
[Serializable]
class A
{
...
[NonSerialized]
public List<B> ListB;
....
}
And then refer to How do you do a deep copy of an object in .NET (C# specifically)? for a cloning function
your interface IDeepCopy is exactly what ICloneable specifies.
class B : ICloneable
{
public object Clone() { return new B(); }
}
and with more friendly implementation :
class B : ICloneable
{
public B Clone() { return new B(); }
// explicit implementation of ICloneable
object ICloneable.Clone() { return this.Clone(); }
}
I stopped using serialization for deep copying anyway, because there is not enough control (not every class needs to be copied the same way). Then I started to implement my own deep copy interfaces and copy every property in the way it should be copied.
Typical ways to copy a referenced type:
Example:
class A
{
// copy constructor
public A(A copy) {}
}
// a referenced class implementing
class B : IDeepCopy
{
object Copy() { return new B(); }
}
class C : IDeepCopy
{
A A;
B B;
object Copy()
{
C copy = new C();
// copy property by property in a appropriate way
copy.A = new A(this.A);
copy.B = this.B.Copy();
}
}
You may think that this a huge amount of work. But at the end, it is easy and straight forward, can be tuned where needed and does exactly what you need.