0

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)."

Stefan
  • 188
  • 2
  • 19
  • 1
    You can't deserialise a `MessageText` to the base class because `Message` will expect a `` element and `MessageText` will expect a `` element. They're not related in XML. You *can* use the same element for both, however: see [this question](http://stackoverflow.com/questions/775647/how-do-i-deserialize-xml-without-knowing-the-type-beforehand), for example. – Charles Mager Aug 04 '16 at 16:14
  • You could use [`XmlSerializer Constructor (Type, XmlRootAttribute)`](https://msdn.microsoft.com/en-us/library/f1wczcys(v=vs.110).aspx) to specify an alternate root element name. But see [Memory Leak using StreamReader and XmlSerializer](https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer/) which explains that such a serializer must be cached and reused. – dbc Aug 04 '16 at 20:19
  • How big is your XML file? Any problem to load it into memory in an `XDocument` for preprocessing? – dbc Aug 06 '16 at 00:42
  • The xml is not big at all, but it would be a bit slow to write every message in a XDocument and then deserialize it. Anyway I found a solution, you can check it below. – Stefan Aug 08 '16 at 22:11

1 Answers1

0

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; }
}
Stefan
  • 188
  • 2
  • 19