Reputation: 10813
I feel like I should know this, but for some reason....
What is the preferred way to serialize a class that derives from a (perhaps abstract) base class, without having to serialize all the way back up the tree? For instance, perhaps you cannot control the class that you are deriving from, but want to use serialization to clone your object (and your object only, not the base).
For example:
// This is a base class that is outside my control, which derives from
// some other base class that I know "nothing" about
public abstract class SomeBaseClass : SomeOtherBaseClass
{
private string mBaseProperty = "Base Property";
public string BaseProperty
{
get { return mBaseProperty; }
set { mBaseProperty = value; }
}
}
// This is the class that I do control
[Serializable()]
private class MyDerivedClass : SomeBassClass
{
// Assume normal constructors, etc.
// Here are some properties
private string mDerivedPropertyOne = String.Empty;
private string DerivedPropertyOne
{
get { return mDerivedPropertyOne ; }
set { mDerivedPropertyOne = value; }
}
private string mDerivedPropertyTwo = String.Empty;
private string DerivedPropertyTwo
{
get { return mDerivedPropertyTwo ; }
set { mDerivedPropertyTwo = value; }
}
// And now a quick-n-dirty Equals override
public override bool Equals(object obj)
{
if (obj == null)
return false;
MyDerivedClass compareTo = obj as MyDerivedClass;
if (compareTo == null)
return false;
return ((String.Compare(this.DerivedPropertyOne,
compareTo.DerivedPropertyOne, true) == 0) &&
(String.Compare(this.DerivedPropertyTwo,
compareTo.DerivedPropertyTwo, true) == 0) &&
}
}
// And while we're at it, here's a simple clone found elsewhere on StackOverflow
public static class ObjectClone
{
public static T Clone<T>(this 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);
}
}
}
As written, this will throw a SerializationException because SomeBaseClass isn't marked as serializable.
Upvotes: 8
Views: 5608
Reputation: 51
You may use XmlRoot("MyDerivedClass") attribute in the your ...BaseClass
Upvotes: 0
Reputation: 606
Short answer: use composition not inheritance. Extract the members you want to serialize into another class and make that one serializable. This will give you the control you want over the lifecycle and the extent of the serialization.
In general, it's a good pattern for serialized objects to be dumb data holders and have any additional logic added by wrapping them. This is reinforced with modern serialization frameworks like protobuf, thrift, avro, which will generate the code behind these serialized objects for you anyway and expect you not to muck with the internals of those classes through inheritance.
Upvotes: 11