0

I'm trying to deserialize a XML using a derived class in C# .NET Framework 4.8:

        string xml =
        "<starttrigger>" +
            "<case>" +
                "<condition>" +
                    "<condition_type>ge</condition_type>" +
                    "<channelname>foobar/bar</channelname>" +
                    "<value>10</value>" +
                "</condition>" +
                "<condition>" +
                    "<condition_type>time</condition_type>" +
                    "<delay_ms>5</delay_ms>" +
                "</condition>" +
            "</case>" +
            "<case>" +
                "<condition>" +
                    "<condition_type>l</condition_type>" +
                    "<channelname>foo/bar</channelname>" +
                    "<value>5</value>" +
                "</condition>" +
            "</case>" +
        "</starttrigger>";

        MemoryStream str = new MemoryStream();
        StreamWriter writer = new StreamWriter(str);
        writer.Write(xml);
        writer.Flush();
        str.Position = 0;

        var serializer = new XmlSerializer(typeof(Trigger));
        var trigger = (Trigger)serializer.Deserialize(str);

In the XML sample, you can see, that can either have a channelname and value OR a delay_ms tag. I want to deserialize this using a derived class to keep by code tidy:

public enum ConditionType
{
    le, ge, l, g, eq, neq, time
}

[XmlInclude(typeof(ConditionTime))]
[XmlInclude(typeof(ConditionComparison))]
public abstract class Condition
{
    [XmlElement(ElementName = "condition_type")]
    public virtual ConditionType ConditionType { get; set; }
}

/// <summary>
/// if ConditionType = le, ge, l, g, eq, neq
/// </summary>
public class ConditionComparison : Condition
{
    [XmlElement(ElementName = "channelname")]
    public string Channelname { get; set; }

    [XmlElement(ElementName = "value")]
    public byte Value { get; set; }
}

/// <summary>
/// if ConditionType = time
/// </summary>
public class ConditionTime : Condition
{
    [XmlElement(ElementName = "delay_ms")]
    public uint DelayMs { get; set; }
}

public class Case
{
    [XmlElement(ElementName = "condition")]
    public List<Condition> Condition { get; set; }
}

[XmlRoot(ElementName = "starttrigger", Namespace = "")]
public class Trigger
{
    [XmlElement(ElementName = "case")]
    public List<Case> Case { get; set; }
}

Using the XmlInclude Attribute it should recognize the derived classes and create the objects accordingly, but it doesn't. In this code sample, I get a InvalidOperationException.

InvalidOperationException: The specified type is abstract: name='Condition', namespace='', at .

If I remove the abstract from the Condition class the code doesn't throw an exception, however the base class is created with only the ConditionType Property. I have also tried giving the XmlSerializer constructor an array with the two extra types.

No matter what i do nothing seems to work. Can you help me?

  • automatically this rather would only work with right `xsi:type` attribute ... feel free to use custom serializer ... or just do on `Condition` class with all posible properties (prolly nullable and exclude null from serialization for this class) ... it really doesn't matter where you put "if" ... if condition_type == this then do that or if condition_type == this then create class thisClass – Selvin Dec 12 '22 at 13:25
  • `XmlSerializer` supports polymorphism in two different ways. 1) You can include an `xsi:type` attribute in the polymorphic element. 2) You can change the element names, from `` to `` or ``. See [Using XmlSerializer to serialize derived classes](https://stackoverflow.com/a/1643424/3744182) by Marc Gravell for details. I recommend choosing one of those two options. – dbc Dec 12 '22 at 17:20
  • 1
    If you **cannot** use either option (because e.g. your XML schema is fixed and you cannot modify it), you will need to deserialize manually, by implementing `IXmlSerializer` (very painful) or deserializing to an `XElement` tree and converting that to your final model. So, can you modify your XML schema? – dbc Dec 12 '22 at 17:22

0 Answers0