以抽象语法树为例,二进制表达式有点像下面这样
class BinaryExpression : ExpressionSyntaxNode
{
private ExpressionSyntaxNode left;
private ExpressionSyntaxNode right;
private Operator optr;
}
如果我想进行自定义序列化,根据https://msdn.microsoft.com/en-us/library/ms973893.aspx ,我需要实现 ISerialized 并拥有类似的东西
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
Left.GetObjectData(info, context);
Right.GetObjectData(info, context);
Optr.GetObjectData(info, context);
}
现在我很困惑我应该如何进行反序列化,因为它没有 SetObjectData 函数,而 otherwsie 可以允许我这样做
public virtual void SetObjectData(SerializationInfo info, StreamingContext context)
{
Left = Left.SetObjectData(info, context);
Right = Right.SetObjectData(info, context);
Optr = Optr.SetObjectData(info, context);
}
而且我不知道特殊的构造函数在这种情况下如何提供帮助,因为我将这些字段(左、右和 optr)反序列化的确切类型在编译时是未知的。 ExpressionSynatxNode也只是一个抽象类,那么这种情况下的解决方案是什么。
最佳答案
您需要添加通过 SerializationInfo.AddValue()
将自身值添加到序列化流中,然后使用 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());
}
}
为了扩展该示例,ExpressionSyntaxNode
类型的 ISerialized
对象的简单类层次结构可能如下所示。请注意流式构造函数的链接以及从派生类型到基类型对 GetObjectData()
的调用:
[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
}
测试示例:
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);
}
}
}
关于c# - 如何在 C# 中自定义反序列化包含自己字段的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38313848/