I’m trying to serialize and deserialize a tree of Node objects. My abstract “Node” class as well as other abstract and concrete classes that derive from it are defined in my “Informa” project. In addition, I’ve created a static class in Informa for serialization / deserialization.
First I’m deconstructing my tree into a flat list of type Dictionary(guid,Node) where guid is the unique id of Node.
I am able to serialize all my Nodes with out a problem. But when I try to deserialize I get the following exception.
Error in line 1 position 227. Element
‘http://schemas.microsoft.com/2003/10/Serialization/Arrays:Value‘
contains data of the
‘Informa:Building’ data contract. The
deserializer has no knowlege of any
type that maps to this contract. Add
the type corresponding to ‘Building’
to the list of known types – for
example, by usying the
KnownTypeAttribute or by adding it to
the list of known types passed to
DataContract Serializer.
All classes that derive from Node, including Building, have the [KnownType(typeof(type t))] attribute applied to them.
My serialization and deserialization methods are below:
public static void SerializeProject(Project project, string filePath)
{
try
{
Dictionary<Guid, Node> nodeDic = DeconstructProject(project);
Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
//serialize
DataContractSerializer ser = new DataContractSerializer(typeof(Dictionary<Guid, Node>),"InformaProject","Informa");
ser.WriteObject(stream,nodeDic);
// Cleanup
stream.Close();
}
catch (Exception e)
{
MessageBox.Show("There was a problem serializing " + Path.GetFileName(filePath) + ". \n\nException:" + e.Message, "Doh!", MessageBoxButtons.OK, MessageBoxIcon.Error);
throw e;
}
}
public static Project DeSerializeProject(string filePath)
{
try
{
Project proj;
// Read the file back into a stream
Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
DataContractSerializer ser = new DataContractSerializer(typeof(Dictionary<Guid, Node>), "InformaProject", "Informa");
Dictionary<Guid, Node> nodeDic = (Dictionary<Guid, Node>)ser.ReadObject(stream);
proj = ReconstructProject(nodeDic);
// Cleanup
stream.Close();
return proj;
}
catch (Exception e)
{
MessageBox.Show("There was a problem deserializing " + Path.GetFileName(filePath) + ". \n\nException:" + e.Message, "Doh!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
KnownTypeis usually applied to the base type – i.e.(note – you can also specify the known-types in the
DataContractSerializerconstructor, without requiring attributes)EDIT RE YOUR REPLY
If the framwork class doesn’t know about all the derived types, then you need to specify the known types when creating the serializer:
This can be combined with (for example)
preserveObjectReferencesetc by replacing thenullin the previous example.END EDIT
However, without something reproducible (i.e.
NodeandBuilding), it is going to be hard to help much.The other odd thing; trees structures are very well suited to things like
DataContractSerializer– there is usually no need to flatten them first, since trees can be trivially expressed in xml. Do you really need to flatten it?Example: