2016-08-04 16 views
0

So habe ich 2 Klassen. Die erste Klasse ist Message und die zweite MessageText-Klasse, die von der Message-Klasse abgeleitet ist.UWP XmlSerializer - Deserialisierung eines Objekts von einer abgeleiteten zur Basisklasse

Dies ist die Nachrichtenklasse:

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; } 
} 

Dies ist die Message Klasse:

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; } 
} 

Dies ist, wie ich tun, um die Serialisierung und Deserialisierung:

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; } 
    } 

Wie Ich verwende die Methoden:

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; 
     //... 
     } 

Also, wenn ich die Nachricht erhalten, möchte ich zunächst an die Basisklasse deserialisieren, so dass ich, welche Art von Meldung kann es ist, und dann ist es deserialisieren auf den richtigen Typ .

Hinweis: kann ich ohne Probleme diesen Ansatz verwenden, wenn ich auf den richtigen Typ deserialisieren möchten, zum Beispiel, wenn ich eine Message Objekt zu einem Message Objekt deserialisieren, aber wenn ich versuche, es ist ein Message Objekt deserialisieren zu Basisklasse Ich erhalte den folgenden Fehler: "Im XML-Dokument (2, 2) ist ein Fehler aufgetreten."

+1

Sie können keine 'MessageText' auf die Basisklasse deserialise weil' Message' wird erwarten, ein '' Element und 'MessageText' wird erwarten, ein' ' Element. Sie sind nicht in XML verwandt. Sie * können jedoch das gleiche Element für beide verwenden: siehe [diese Frage] (http://stackoverflow.com/questions/775647/how-doi-i-deserialize-xml-without-knowing-the-type-beforehand), beispielsweise. –

+0

Sie könnten ['XmlSerializer-Konstruktor (Typ, XmlRootAttribute)'] (https://msdn.microsoft.com/en-us/library/f1wczcys (v = vs.110) .aspx) verwenden, um einen alternativen Stammelementnamen anzugeben . Aber siehe [Speicherleck mit StreamReader und XmlSerializer] (https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer/), was erklärt, dass ein solcher Serializer zwischengespeichert und wiederverwendet werden muss. – dbc

+0

Wie groß ist Ihre XML-Datei? Irgendein Problem, um es in einem 'XDocument' in den Speicher zur Vorverarbeitung zu laden? – dbc

Antwort

0

Da der XmlSerializer das Root-Element erwartet und das Root-Element der MessageText-Klasse ist, verwende ich einfach den folgenden Code, um das Root-Element der MessageText-Klasse zu ändern und das Objekt in eine Message zu deserialisieren MessageText-Klasse.

[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; } 
} 
Verwandte Themen