In C#, how do I use an XmlSerializer
to deserialize an object that might be of a base class, or of any of several derived classes without knowing the type befor
If you're not set upon using the XmlSerializer
you can use the DataContractSerializer with the KnownType attribute instead.
All you need to do is add a KnownType
attribute to the parent class for each sub class and the DataContractSerializer
will do the rest.
The DataContractSerializer
will add type information when serializing to xml and use that type information when deserializing to create the correct type.
For example the following code:
[KnownType( typeof( C2 ) )]
[KnownType( typeof( C3 ) )]
public class C1 {public string P1 {get;set;}}
public class C2 :C1 {public string P2 {get;set;}}
public class C3 :C1 {public string P3 {get;set;}}
class Program
{
static void Main(string[] args)
{
var c1 = new C1{ P1="c1"};
var c2 = new C2{ P1="c1", P2="c2"};
var c3 = new C3{ P1="c1", P3="c3"};
var s = new DataContractSerializer( typeof( C1 ) );
Test( c1, s );
Test( c2, s );
Test( c3, s );
}
static void Test( C1 objectToSerialize, DataContractSerializer serializer )
{
using ( var stream = new MemoryStream() )
{
serializer.WriteObject( stream, objectToSerialize );
stream.WriteTo( Console.OpenStandardOutput() );
stream.Position = 0;
var deserialized = serializer.ReadObject( stream );
Console.WriteLine( Environment.NewLine + "Deserialized Type: " + deserialized.GetType().FullName );
}
}
}
Will output :
c1
Deserialized Type: ConsoleApplication1.C1
c1 c2
Deserialized Type: ConsoleApplication1.C2
c1 c3
Deserialized Type: ConsoleApplication1.C3
In the output you'll notice the xml for c2 and c3 contained extra type information which allowed the DataContractSerializer.ReadObject
to create the correct type.