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?