I have an abstract class that I'm trying to serialize and deserialize the concrete implementations of. In my abstract base class I have this:
[DataContract]
public class MyAbstractBase
{
[DataMember]
public string Foo { get; set; }
// some other abstract methods that derived classes have to implement
}
And to that class I add a method to serialize:
public string SerializeBase64()
{
// Serialize to a base 64 string
byte[] bytes;
long length = 0;
MemoryStream ws = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(this.GetType());
XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ws);
serializer.WriteObject(binaryDictionaryWriter, this);
binaryDictionaryWriter.Flush();
length = ws.Length;
bytes = ws.GetBuffer();
string encodedData = bytes.Length + ":" + Convert.ToBase64String(bytes, 0, bytes.Length, Base64FormattingOptions.None);
return encodedData;
}
This seems to work fine, in that it produces "something" and doesn't actually throw any errors.
Of course, the problem comes with deserialization. I added this:
public static MyAbstractBase DeserializeBase64(string s)
{
int p = s.IndexOf(':');
int length = Convert.ToInt32(s.Substring(0, p));
// Extract data from the base 64 string!
byte[] memorydata = Convert.FromBase64String(s.Substring(p + 1));
MemoryStream rs = new MemoryStream(memorydata, 0, length);
DataContractSerializer serializer = new DataContractSerializer(typeof(MyAbstractBase ), new List<Type>() { typeof(SomeOtherClass.MyDerivedClass) });
XmlDictionaryReader binaryDictionaryReader = XmlDictionaryReader.CreateBinaryReader(rs, XmlDictionaryReaderQuotas.Max);
return (MyAbstractBase)serializer.ReadObject(binaryDictionaryReader);
}
I thought by adding the "known types" to my DataContractSerializer
, it would be able to figure out how to deserialize the derived class, but it appears that it doesn't. It complains with the error:
Expecting element 'MyAbstractBase' from namespace 'http://schemas.datacontract.org/2004/07/MyApp.Foo'.. Encountered 'Element' with name 'SomeOtherClass.MyDerivedClass', namespace 'http://schemas.datacontract.org/2004/07/MyApp.Foo.Bar'.
So any idea what I'm missing here?
I put together a simple demonstration of the problem on a dot net fiddle here:
http://dotnetfiddle.net/W7GCOw
Unfortunately, it won't run directly there because it doesn't include the System.Runtime.Serialization
assemblies. But if you drop it into a Visual Studio project, it will serialize fine, but balks at deserialization.