1

einen abstrakten Syntaxbaum Nehmen Sie zum Beispiel, ein binärer Ausdruck wird sieht etwas wie die folgendenWie deserialize ein Objekt anzufertigen, die ein Feld von selbst in C# enthält

class BinaryExpression : ExpressionSyntaxNode 
{ 
    private ExpressionSyntaxNode left; 
    private ExpressionSyntaxNode right; 
    private Operator optr; 
} 

Wenn ich eine customize Serialisierung tun will nach https://msdn.microsoft.com/en-us/library/ms973893.aspx, muss ich ISerializable und haben so etwas wie dieses

public virtual void GetObjectData(SerializationInfo info, StreamingContext context) 
{ 
    Left.GetObjectData(info, context); 
    Right.GetObjectData(info, context); 
    Optr.GetObjectData(info, context); 
} 

Jetzt bin ich sehr verwirrt, wie soll ich tun Deserialisierung implementieren, da es keine SetObjectData hat Funktion, die otherwsie mich

public virtual void SetObjectData(SerializationInfo info, StreamingContext context) 
{ 
    Left = Left.SetObjectData(info, context); 
    Right = Right.SetObjectData(info, context); 
    Optr = Optr.SetObjectData(info, context); 
} 

tun haben dürfen konnte, und ich weiß nicht, wie die speziellen Konstruktor in diesem Fall helfen kann cos den genauen Typ I werden diejenigen Feld werden Deserialisieren (links, rechts und OPTR) in unbekannt zur Kompilierzeit. ExpressionSynatxNode ist auch nur eine abstrakte Klasse, also was ist die Lösung in diesem Fall.

Antwort

0

Anstatt SetObjectData() und GetObjectData() auf den Werten der Felder in Ihrem ISerializable Typ aufrufen, müssen Sie die Werte selbst zum Serialisierungsstream über SerializationInfo.AddValue() hinzufügen möchten, dann holen die deserialisiert Werte aus mit GetValue():

[Serializable] 
class BinaryExpression : ExpressionSyntaxNode, ISerializable 
{ 
    private ExpressionSyntaxNode left; 
    private ExpressionSyntaxNode right; 
    private Operator optr; 

    public BinaryExpression(ExpressionSyntaxNode left, ExpressionSyntaxNode right, Operator optr) 
    { 
     this.left = left; 
     this.right = right; 
     this.optr = optr; 
    } 

    #region ISerializable Members 

    protected BinaryExpression(SerializationInfo info, StreamingContext context) 
     : base(info, context) 
    { 
     left = (ExpressionSyntaxNode)info.GetValue("left", typeof(ExpressionSyntaxNode)); 
     right = (ExpressionSyntaxNode)info.GetValue("right", typeof(ExpressionSyntaxNode)); 
     optr = (Operator)info.GetValue("optr", typeof(Operator)); 
    } 

    public override void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     base.GetObjectData(info, context); 
     info.AddValue("left", left); 
     info.AddValue("right", right); 
     info.AddValue("optr", optr); 
    } 

    #endregion 

    public override string ToString() 
    { 
     return string.Format("({0} {1} {2})", left.ToString(), optr.ToString(), right.ToString()); 
    } 
} 

Um das Beispiel zu erweitern, könnte eine einfache Klassenhierarchie von ISerializable Objekten vom Typ ExpressionSyntaxNode wie folgt aussehen. Beachten Sie die Verkettung von Streaming-Konstrukteuren und ruft GetObjectData() zur Basistyp abgeleitet:

[Serializable] 
abstract class ExpressionSyntaxNode : ISerializable 
{ 
    protected ExpressionSyntaxNode() 
    { 
    } 

    #region ISerializable Members 

    protected ExpressionSyntaxNode(SerializationInfo info, StreamingContext context) 
    { 
    } 

    public virtual void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
    } 

    #endregion 
} 

[Serializable] 
abstract class ValueExpression<T> : ExpressionSyntaxNode, ISerializable where T : IConvertible 
{ 
    T value; 

    public T Value { get { return value; } } 

    public ValueExpression(T value) 
    { 
     this.value = value; 
    } 

    public override void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     base.GetObjectData(info, context); 
     info.AddValue("value", value); 
    } 

    protected ValueExpression(SerializationInfo info, StreamingContext context) 
     : base(info, context) 
    { 
     this.value = (T)info.GetValue("value", typeof(T)); 
    } 

    public override string ToString() 
    { 
     if (value == null) 
      return ""; 
     return value.ToString(); 
    } 
} 

[Serializable] 
class BooleanExpression : ValueExpression<bool>, ISerializable 
{ 
    public BooleanExpression(bool value) : base(value) { } 

    public override void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     base.GetObjectData(info, context); 
    } 

    protected BooleanExpression(SerializationInfo info, StreamingContext context) 
     : base(info, context) 
    { 
    } 
} 

[Serializable] 
public enum Operator 
{ 
    And, 
    Or 
} 

Testbeispiel:

public class TestClass 
{ 
    public static void Test() 
    { 
     var expression = new BinaryExpression(
      new BinaryExpression(new BooleanExpression(false), new BooleanExpression(true), Operator.And), 
      new BinaryExpression(new BooleanExpression(true), new BooleanExpression(false), Operator.Or), 
      Operator.Or); 

     Debug.WriteLine("Initial expression: "); 
     Debug.WriteLine(expression); // "((False And True) Or (True Or False))" 

     if (expression.ToString() != "((False And True) Or (True Or False))") 
      throw new InvalidOperationException(); 

     var binary = BinaryFormatterHelper.ToBinary(expression); 

     var expression2 = BinaryFormatterHelper.FromBinary<BinaryExpression>(binary); 

     Debug.WriteLine("Deserialized expression: "); 
     Debug.WriteLine(expression2); 

     if (expression.ToString() != expression2.ToString()) 
     { 
      throw new InvalidOperationException(); 
     } 
     else 
     { 
      Debug.WriteLine("Deserialized and original expressions are identical"); 
     } 
    } 
} 

public static partial class BinaryFormatterHelper 
{ 
    public static byte[] ToBinary<T>(T obj) 
    { 
     using (var stream = new MemoryStream()) 
     { 
      new BinaryFormatter().Serialize(stream, obj); 
      return stream.ToArray(); 
     } 
    } 

    public static T FromBinary<T>(byte[] data) 
    { 
     using (var stream = new MemoryStream(data)) 
     { 
      var formatter = new BinaryFormatter(); 
      var obj = formatter.Deserialize(stream); 
      if (obj is T) 
       return (T)obj; 
      return default(T); 
     } 
    } 
} 
+0

auf Ihrer Antwort das bedeutet ich habe keine Möglichkeit, den Konstruktor zu verwenden, die deserialisieren BinaryExpression obj? – user1935724

+0

@ user1935724 - Ja, es ist nicht so gedacht. Der Serializer selbst ruft den Konstruktor auf und übergibt eine "SerializationInfo", die mit den Feldwerten für dieses bestimmte Objekt gefüllt ist und aus dem Serialisierungsstrom extrahiert wird. Da die verschachtelten Objekte intern natürlich unterschiedliche Feldwerte enthalten, ist beim Deserialisieren eine andere "SerializationInfo" erforderlich. – dbc