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.
You can prevent member variables from being serialized by marking them with the NonSerialized attribute as follows. If possible, make an object that could contain security-sensitive data nonserializable. If the object must be serialized, apply the NonSerialized attribute to specific fields that store sensitive data.
There is no direct way to prevent sub-class from serialization in java. One possible way by which a programmer can achieve this is by implementing the writeObject() and readObject() methods in the subclass and needs to throw NotSerializableException from these methods.
In order to prevent subclass from serialization we need to implement writeObject() and readObject() methods which are executed by JVM during serialization and deserialization also NotSerializableException is made to be thrown from these methods.
WhenWritingDefault - The property is ignored on serialization if it's a reference type null , a nullable value type null , or a value type default . WhenWritingNull - The property is ignored on serialization if it's a reference type null , or a nullable value type null .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With