Reputation: 13
Abstract supertype Animal has many subtypes, Cat, Dog etc. These subtypes have only a constructor and overrides of virtual methods found in Animal - ie they have NO Properties or Methods unique to themselves. Class Zoo has many references to, and Lists of Animals, but does not know about or will ever need to know about Cats, Dogs etc. What is the most best way of enabling deep copying of Zoo? , preferably with little or no new code in Cat, Dog etc.
Upvotes: 1
Views: 238
Reputation: 16991
One quick and easy way to deeply clone an object is to serialize it to a MemoryStream
and then deserialize it back to an object graph. The deserialized copy will be a deep-cloned graph with no references to the original objects. It can be a bit more memory and CPU intensive than manually cloneining the object, but it is significantly less coding work; the end result is usually acceptable.
Here is one implementation taken from CodeProject:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <span class="code-SummaryComment"><summary></span>
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// <span class="code-SummaryComment"></summary></span>
public static class ObjectCopier
{
/// <span class="code-SummaryComment"><summary></span>
/// Perform a deep Copy of the object.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><typeparam name="T">The type of object being copied.</typeparam></span>
/// <span class="code-SummaryComment"><param name="source">The object instance to copy.</param></span>
/// <span class="code-SummaryComment"><returns>The copied object.</returns></span>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
It can be called like this:
ObjectCopier.Clone(objectBeingCloned);
Upvotes: 1
Reputation: 156978
If your concern is that you need to create a new Clone
implementation, just to get the right type (since the type of this
in a base class is a moving target), you could use Activator.CreateInstance
to create a new instance of the current type, for all types that override Animal
:
var copy = (Animal)Activator.CreateInstance(this.GetType());
copy.HasClaws = this.HasClaws; // copy Animal properties
You need a parameterless constructor in order to make this Activator.CreateInstance
call work.
Upvotes: 3