2016-08-04 14 views
0

したがって、2つのクラスがあります。最初のクラスはMessageで、2つ目はMessageクラスから派生したMessageTextクラスです。UWP XmlSerializer - 派生クラスから基本クラスへのオブジェクトの逆シリアル化

これはMessageクラスです:

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

これはMessageTextクラスです:

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

これは私がシリアライズとデシリアライズを行う方法です。

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

私は私が最初に私はそれがあるメッセージの種類を見ることができるように、基本クラスにそれをデシリアライズし、その後、正しい型にそれをデシリアライズするメッセージを受信したときにそう

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

:私は、メソッドを使用します。

注:私は正しい型にデシリアライズしたい場合、私はMessageTextオブジェクトにMessageTextオブジェクトをデシリアライズする場合、私は例えば、問題なくこのアプローチを使用することができますが、私はそのにMessageTextオブジェクトをデシリアライズしようとした場合基本クラス私は次のエラーが発生します: "XML文書(2、2)にエラーがあります。"

+1

'message'では、' '要素と' MessageText'が '' 要素を期待することを期待しますので、あなたは、基本クラスに 'MessageText'をdeserialiseすることはできません。それらはXMLでは関係ありません。あなたは*しかし、両方のために同じ要素を使用することができます:[この質問を参照してください(http://stackoverflow.com/questions/775647/how-do-i-deserialize-xml-without-knowing-the-type-beforehand )、 例えば。 –

+0

代替ルート要素名を指定するには、['XmlSerializer Constructor(Type、XmlRootAttribute)'](https://msdn.microsoft.com/en-us/library/f1wczcys(v = vs.110).aspx) 。しかし、このようなシリアライザをキャッシュして再利用する必要があることを説明する[StreamReaderとXmlSerializerを使用したメモリリーク](https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer/)を参照してください。 – dbc

+0

XMLファイルのサイズはどれくらいですか?前処理のために 'XDocument'のメモリにロードするのに問題はありますか? – dbc

答えて

0

XmlSerializerはルート要素が存在し、MessageTextクラスのルート要素が必要なので、次のコードを使用してMessageTextクラスのルート要素を変更するだけで、オブジェクトをメッセージに逆シリアル化できますMessageTextクラス。

[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; } 
} 
関連する問題