I’m new to serialization, so most likely I am missing something obvious!
I have a class called ResultsCollection that is a four-dimension data structure — a collection of objects that are derived from the DataSet class. Each modified DataSet holds a collection of objects derived from DataTable. The relevant bits of code are:
[Serializable]
public class ResultsCollection : CollectionBase, ISerializable
{
// indexer
public MyDataSet this[int index] { get { return (MyDataSet)List[index]; } }
}
[Serializable]
public class MyDataSet : DataSet, ISerializable
{
// member variable that *overrides* the Tables property of the standard DataSet class
public new TablesCollection Tables;
}
[Serializable]
public class TablesCollection : CollectionBase, ISerializable
{
// indexer
public MyDataTable this[int index] { get { return (MyDataTable)List[index]; } }
}
[Serializable]
public class MyDataTable : DataTable, ISerializable
{
...
}
I have implemented the ISerializable interface by including a public Serialization constructor and a public GetObjectData function, as shown here:
// ResultsCollection -- serialize all variables and also the inner list itself
public ResultsCollection(SerializationInfo info, StreamingContext ctxt) : base()
{
_memberVariable = (bool)info.GetValue("_memberVariable", typeof(bool));
ArrayList innerList = (ArrayList)info.GetValue("List", typeof(ArrayList));
InnerList.AddRange(innerList);
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("_memberVariable", _memberVariable);
info.AddValue("List", InnerList);
}
// MyDataSet -- call standard base-class (DataSet) serialization functions in addition to serializing members
public MyDataSet(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)
{
_memberVariable = (bool)info.GetValue("_memberVariable", typeof(bool));
Tables = (TablesCollection)info.GetValue("Tables", typeof(TablesCollection));
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
base.GetObjectData(info, ctxt);
info.AddValue("_memberVariable", _memberVariable);
info.AddValue("Tables", Tables);
}
// TablesCollection -- serialize all variables and also the inner list itself
public TablesCollection(SerializationInfo info, StreamingContext ctxt) : base()
{
_memberVariable = (bool)info.GetValue("_memberVariable", typeof(bool));
ArrayList innerList = (ArrayList)info.GetValue("List", typeof(ArrayList));
InnerList.AddRange(innerList);
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("_memberVariable", _memberVariable);
info.AddValue("List", InnerList);
}
// MyDataTable -- call standard base-class (DataTable) serialization functions in addition to serializing members
public MyDataSet(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)
{
_memberVariable = (bool)info.GetValue("_memberVariable", typeof(bool));
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
base.GetObjectData(info, ctxt);
info.AddValue("_memberVariable", _memberVariable);
}
I have a single ResultsCollection object that I want to store in ViewState, in order to retrieve it on the next post-back (hence all this trouble). For the initial request, things appear to be working: I have set break-points in the Serialization functions and the data members are indeed being serialized. However, upon deserialization, the member variables are loaded properly but the List objects are full of null members. My code crashes out when I try to retrieve the DataSetName property from the first MyDataSet object in the ResultsCollection.
It turns out that CollectionBase and ISerializable are incompatible, possibly because the InnerList property of CollectionBase is read-only. Therefore what I needed to do was to remove the ISerializable definitions from the two CollectionBase-derived classes, i.e.: