Open
Description
Description
When a base class implements IXmlSerializable then XmlSerializer Deserializing tries to create an instance of base class and calls it's virtual ReadXml instead of the overriden ReadXml in the derived class.
Reproduction Steps
In the following example the deserializer is trying to make an instance of the base class instead of the derived one.
Repository with an example: https://github.com/MMariusch/Example
The code:
public class TestClass
{
[XmlElement("AClass", typeof(AClass))]
List<BaseClass> objects = new List<BaseClass>();
public TestClass(){}
public void SaveToFile()
{
objects.Add(new AClass("someString"));
objects.Add(new AClass("anotherString"));
var xmlSerializer = new XmlSerializer(typeof(List<BaseClass>));
using (var writer = new StreamWriter("SaveList.xml"))
{
xmlSerializer.Serialize(writer, objects);
}
}
public void LoadFromFile()
{
if (File.Exists("SaveList.xml"))
{
using (var reader = new StreamReader("SaveList.xml"))
{
var deserializedList = new XmlSerializer(typeof(List<BaseClass>)).Deserialize(reader) as List<BaseClass>;
if (deserializedList != null && deserializedList.Count > 0)
{
objects = deserializedList;
}
}
}
}
}
[XmlInclude(typeof(AClass))]
public class BaseClass : IXmlSerializable
{
public BaseClass() { }
public XmlSchema GetSchema() { return null; }
public virtual void ReadXml(XmlReader reader)
{
Console.Write("It shouldn't be triggered.");
}
public virtual void WriteXml(XmlWriter writer) { }
}
public class AClass : BaseClass
{
private string _stringVar;
public string StringVar { get => _stringVar; private set => _stringVar = value; }
public AClass() { }
public AClass(string stringVar)
{
_stringVar = stringVar;
}
public override void ReadXml(XmlReader reader)
{
reader.MoveToContent();
var anyElements = !reader.IsEmptyElement;
reader.ReadStartElement();
if (anyElements)
{
_stringVar = reader.ReadElementContentAsString("StringVar", "");
reader.ReadEndElement();
}
}
public override void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("xsi", "type", null, "AClass");
writer.WriteElementString("StringVar", _stringVar);
}
}
Expected behavior
Should create an instance of the derived class.
Actual behavior
Creates an instance of the base class.
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response