Pregunta

I am trying to serialize a series of subclasses deriving from a single abstract superclass WorldObject to XML, using the IXmlSerializable interface. I have to use this interface, as I want the class to subscribe to some events as it is deserializing.

Using this answer, I came up with the following code:

[XmlInclude(typeof(SubType1))
,XmlInclude(typeof(SubType2))] // etc, includes all subtypes
public abstract class WorldObject : IComparable, IXmlSerializable

public void WriteXml(System.Xml.XmlWriter writer)
{
    Type[] extraTypes = new Type[8];
    // (...) adding types to array here
    var worldObjectSerializer = new XmlSerializer(typeof(List<WorldObject>), extraTypes);
}

The last line where the XmlSerializer is initialized throws a runtime error: System.MissingMethodException: Cannot create an abstract class 'Namespace.WorldObject'. The same error is thrown when I try to use typeof(WorldObject) instead of typeof(List<WorldObject>).

I have also tried setting the XMLRoot to the same value in every class as demonstrated here, but the error persists.

¿Fue útil?

Solución

I never found a way to get rid of the exception, but I found a workaround. The solution simply writes its own element wrapper with the type as its name, calls the WriteXml function and writes the end element.

foreach (WorldObject wO in list)
        {
             writer.WriteStartElement(wO.GetType().ToString());

             wO.WriteXml(writer);

             writer.WriteEndElement();
        }

This allows you to deserialize the concrete implementation of the abstract class as well. The wO.GetType().ToString() creates a string with the concrete class and namespaces. Then you can create an XmlSerializer where the type is gleaned from the element wrapper name, like so:

Type t = Type.GetType(reader.LocalName);
XmlSerializer worldObjectSerializer = new XmlSerializer(t, new XmlRootAttribute(reader.LocalName));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top