I'm trying to make a class I wrote serializable. It contains several static readonly fields that never change after construction, so they don't need to be serialized. I'm having trouble finding a way to re-set them after de-serialization that doesn't weaken the access in the base class. Here's a simplified example, starting with a non-serialisable base and derived class:
internal abstract class MyBase
{
private readonly List<int> myIntList = new List<int> ();
internal MyBase (List<int> anIntList)
{
this.myIntList = anIntList;
}
}
The derived class doesn't need to access the list, so the field can be private readonly in the base class, and the derived class set it like this:
internal sealed class MyDerived : MyBase
{
private static readonly List<int> derivedIntList = new List<int> { 1, 2, 3 };
internal MyDerived () : base (MyDerived.derivedIntList)
{
}
}
Now I want to make my derived class serializable. Since the list contents don't change, there's no need to serialize them, so I just put a DataContract attribute on both classes.
I serialize the derived class to disk like this:
private static void SeralizeDerived (string path)
{
MyDerived derived = new MyDerived ();
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Create))
{
serializer.WriteObject (stream, derived);
stream.Flush ();
}
}
and deserialize it like this:
private static void DeserializeDerived (string path)
{
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Open, FileAccess.Read))
{
MyDerived derived = serializer.ReadObject (stream) as MyDerived;
// debugger shows derived.myIntList as null, as expected
}
}
As per the comment in DeserializeDerived, the value of derived.myIntList is null. This isn't surprising to me - I didn't ask it to be serialized, and I haven't done anything to re-create it after deserialization.
The problem is this: The only way I know to fix this is to change the access to myIntList to make it protected, and have an OnDeserialized method in the MyDerived class that (re)sets myIntList:
private void ReInitialize ()
{
base.myIntList = MyDerived.derivedIntList;
}
[OnDeserialized]
private void OnDeserialized (StreamingContext context)
{
this.ReInitialize ();
}
internal MyDerived () : base ()
{
this.ReInitialize ();
}
This feels wrong - I don't want to weaken the access to the base class members, and initializing the members field-by-field in the derived constructor is more error-prone. The question is: How can I keep the same member protection but still support serialization?