2013-02-19 3 views
3

Я пытаюсь использовать protobuf-net для сериализации объектов. Я не уверен, поддерживается ли то, что я пытаюсь сделать с наследованием, но я думал, что проверю и посмотрю, если это так, или если я просто делаю что-то неправильно.Сериализация и десериализация с полиморфизмом и 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, и они все немного отличаются от этого примера (насколько я понял их).

ответ

8

Вы будете пинать себя. Код прекрасно за исключением одной вещи - вы забыли перемотать поток:

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

Как это было, Deserialize читал 0 байт (потому что это было в конце), таким образом, пытается создать родительский тип. Пустой поток вполне применим в терминах спецификации protobuf - это просто объект без каких-либо интересных значений.

+1

Ох. Мои. Heck. Серьезно, я потратил дольше на это, чем следовало бы. Спасибо огромное! – Cornstalks

+3

@Cornstalks Я сказал, что вы бы себя разыграли :) Но серьезно: спасибо за публикацию воспроизводимого примера - это делает так легко помогать. –

+1

сам кикер проверка, спасибо! – thumbmunkeys

Смежные вопросы