Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Serialization of Base Class

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.

like image 495
Wonko the Sane Avatar asked Dec 20 '11 18:12

Wonko the Sane


People also ask

How can we prevent serialization?

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.

How do you restrict class in serialization?

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.

How can we prevent child class from being serialized?

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.

How do you ignore property serializable?

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 .


1 Answers

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.

like image 55
supermem613 Avatar answered Oct 30 '22 06:10

supermem613