views:

254

answers:

3

I have a derived class that adds only methods to a base class. How can serialize the derived class so that it matches the serialization of the base class? i.e. The serialized xml of the derived class should look like:

<BaseClass>
  ...
</BaseClass>

e.g. The following will throw an InvalidOperationException "The type DerivedClass was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."

Class BaseClass {}

Class DerivedClass : BaseClass {}

DerivedClass derived = new DerivedClass();

StreamWriter stream = new StreamWriter("output file path");
XmlSerializer serializer = new XmlSerializer(GetType(BaseClass));
serializer(stream, derived);
A: 

I haven't tried it but can you not just cast it ?

serializer(stream, (BaseClass)derived);

Edit

Also, if you want to have a single XmlSerialiser that can cope with multiple derived classes & the base class then you need to specify all of the types in the XmlSerialiser constructor.

  XmlSerializer serializer = new XmlSerializer(typeof(BaseClass), new Type[] {typeof(DerivedClass)});

Then it will happily serialize multiple types. However you will also have to use the solution mentioned above to get the output xml to match between classes.

Leigh Shayler
No the same InvalidOperationException is thrown
Chris Herring
+4  A: 

You'll have to pass GetType(DerivedClass) to the serializer constructor, it must match the type of the object you serialize. You can use the <XmlRoot> attribute to rename to the root element. This example code worked as intended:

using System;
using System.Xml.Serialization;
using System.IO;

class Program {
  static void Main(string[] args) {
    var obj = new DerivedClass();
    obj.Prop = 42;
    var xs = new XmlSerializer(typeof(DerivedClass));
    var sw = new StringWriter();
    xs.Serialize(sw, obj);
    Console.WriteLine(sw.ToString());

    var sr = new StringReader(sw.ToString());
    var obj2 = (BaseClass)xs.Deserialize(sr);
    Console.ReadLine();
  }
}

public class BaseClass {
  public int Prop { get; set; }
}
[XmlRoot("BaseClass")]
public class DerivedClass : BaseClass { }
Hans Passant
does the job, thanks.
Chris Herring
A: 

After a little bit of googling ;) I can say that you'll need some more code and implement IXmlSerializable for your base class, declaring all interface methods as virtual and overriding them on your derived class. Here's a sample topic and similar problem resolved by interface mentioned.

terR0Q