Stefan Stefan - 3 months ago 59
C# Question

UWP XmlSerializer - Deserialization of an object from a derived to base class

So I have 2 classes. The first class is Message and the second one is MessageText class that derives from the Message class.

This is the Message class:

public class Message
{
public Message(Guid from, Guid to, MessageType type, DateTime sentAt)
{
From = from;
To = to;
Type = type;
SentAt = sentAt;
}

public Message()
{
}

public Guid From { get; set; }
public Guid To { get; set; }
public MessageType Type { get; set; }
public DateTime SentAt { get; set; }
}


This is the MessageText class:

public class MessageText : Message
{
public MessageText(Guid from, Guid to, MessageType type, DateTime sentAt, string text)
: base(from, to, type, sentAt)
{
this.Text = text;
}

public MessageText()
{
}

public string Text { get; set; }
}


This is how I do the serialization and deserialization:

public static byte[] ConvertToStream(object obj)
{
try
{
XmlSerializer bf = new XmlSerializer(obj.GetType());

using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
catch { return new byte[0]; }
}

public static object ConvertFromStream<T>(byte[] data)
{
try
{
XmlSerializer bf = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(data))
{
return bf.Deserialize(ms);
}
}
catch { return null; }
}


How I use the methods:

Byte[] buffer = XMLHelper.ConvertToStream(message);
// Now send the message
// ...
/// When I receive the message
Message msg = (Message)XMLHelper.ConvertFromStream<Message>(data);
switch (msg.Type)
{
case EMessageType.Text:
if (OnMessageTextReceivedEvent != null)
{
MessageText msgT = (MessageText)XMLHelper.ConvertFromStream(data);
OnMessageTextReceivedEvent(msgT, EventArgs.Empty);
}
break;
//...
}


So when I receive the message I firstly want to deserialize it to the base class, so that I can see what type of message it is, and then to deserialize it to the correct type.

Note: I can use this approach without a problem if I want to deserialize to the correct type, for example if I deserialize a MessageText object to a MessageText object, but if I try to deserialize a MessageText object to its base class I get the following error: "There is an error in XML document (2, 2)."

Answer

Since the XmlSerializer expects the root element to be and the root element of the MessageText class is I just use the following code to change the root element of the MessageText class and now I can deserialize the object into a Message and/or MessageText class.

[XmlRoot("Message")]
public class MessageText : Message
{
    public MessageText(Guid from, Guid to, MessageType type, DateTime sentAt, string text)
        : base(from, to, type, sentAt)
    {
        this.Text = text;
    }

    public MessageText()
    {
    }

    public string Text { get; set; }
}