代码之家  ›  专栏  ›  技术社区  ›  Cornstalks

利用多态性和Protobuf-net进行串行化和反串行化

  •  4
  • Cornstalks  · 技术社区  · 12 年前

    我正在尝试使用 protobuf-net 以序列化对象。我不确定我试图用继承做的事情是否得到支持,但我想我应该检查一下,看看是不是得到了支持,或者我只是做错了什么。

    本质上,我试图序列化一些子类,然后反序列化它,但只使用基类引用。演示:

    using UnityEngine;
    using System.Collections;
    using ProtoBuf;
    
    public class main : MonoBehaviour
    {
        // If I don't put "SkipConstructor = true" I get
        // ProtoException: No parameterless constructor found for Parent
        // Ideally, I wouldn't have to put "SkipConstructor = true" but I can if necessary
        [ProtoContract(SkipConstructor = true)]
        [ProtoInclude(1, typeof(Child))]
        abstract class Parent
        {
            [ProtoMember(2)]
            public float FloatValue
            {
                get;
                set;
            }
    
            public virtual void Print()
            {
                UnityEngine.Debug.Log("Parent: " + FloatValue);
            }
        }
    
        [ProtoContract]
        class Child : Parent
        {
            public Child()
            {
                FloatValue = 2.5f;
                IntValue   = 13;
            }
    
            [ProtoMember(3)]
            public int IntValue
            {
                get;
                set;
            }
    
            public override void Print()
            {
                UnityEngine.Debug.Log("Child: " + FloatValue + ", " + IntValue);
            }
        }
    
        void Start()
        {
            Child child = new Child();
            child.FloatValue = 3.14f;
            child.IntValue   = 42;
    
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
    
            // I don't *have* to do this, I can, if needed, just use child directly.
            // But it would be cool if I could do it from an abstract reference
            Parent abstractReference = child; 
    
            ProtoBuf.Serializer.Serialize(ms, abstractReference);
    
            ProtoBuf.Serializer.Deserialize<Parent>(ms).Print();
        }
    }
    

    该输出:

    Parent: 0

    我希望它输出的是:

    Child: 3.14 42

    这可能吗?如果是这样,我做错了什么?我读过SO上关于继承和protobuf-net的各种问题,它们都与这个例子有点不同(就我所理解的而言)。

    1 回复  |  直到 12 年前
        1
  •  10
  •   Marc Gravell    12 年前

    你会踢自己的。代码很好,除了一件事——你忘了倒带流:

    ProtoBuf.Serializer.Serialize(ms, abstractReference);
    ms.Position = 0; // <========= add this
    ProtoBuf.Serializer.Deserialize<Parent>(ms).Print();
    

    事实上 Deserialize 正在读取0个字节(因为它在末尾),因此试图创建父类型。根据protobuf规范,空流是完全有效的——它只意味着一个没有任何有趣值的对象。