Using Protobuf-net, I get an exception about an unknown wire-type with List<Subclassable>

烈酒焚心 提交于 2019-12-11 03:57:41

问题


I've started to convert our Unity/iOS game to save state with Protobuf-net. It looked like things were working OK, until I added this instance variable to GameState

[ProtoMember(10)]
public List<Unit> fUnits;

Unit is

[ProtoContract]
[ProtoInclude(21, typeof(ArtilleryUnit))]
[ProtoInclude(22, typeof(CavalryArtilleryUnit))]
[ProtoInclude(23, typeof(CavalryUnit))]
[ProtoInclude(24, typeof(InfantryUnit))]
[Serializable]
public class Unit : IActionHandler

This is the first subclass I've serialized. I'm testing my code by deserializing right after writing

using (Stream memoryStream = new MemoryStream()) {
    byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
    memoryStream.Write(data, 0, data.Length);
    memoryStream.Position = 0;
    WBTSSerializer deserializer = new WBTSSerializer();

    testState = new GameState();
    deserializer.Deserialize(memoryStream, testState, typeof(GameState));
}

and I get

ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354
  at ProtoBuf.ProtoReader.SkipField () [0x00000] in <filename unknown>:0
  at WBTSSerializer.Read (wbts.Unit , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
  at WBTSSerializer.Read (wbts.GameState , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
  at WBTSSerializer.Deserialize (Int32 , System.Object , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader reader, System.Type type, System.Object value, Boolean noAutoCreate) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type, ProtoBuf.SerializationContext context) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type) [0x00000] in <filename unknown>:0
  at wbts.Game.SaveGame (System.String filename) [0x000c1] in /Users/david/Shenandoah/WBTS/wbts/wbts/Game.cs:620

Needless to say, I've checked for overwriting (it's a brand new file). And, if I take out the ProtoMember(10), it won't throw.

If I take out the ProtoInclude lines, I get an error about the subclasses. And, if I take out ProtoMember within Unit, it still throws.

If it matters, I am currently just running this from Xamarin (on Mac OS X — I'm an iOS developer). But that's just for ease of testing, I have managed to hit Protobuf-net with enough sticks to make it run on an iPad.


回答1:


My eye is drawn immediately to:

byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);

Protobuf data is not text, and is not UTF-8 (although strings inside protobuf data are UTF-8, by coincidence) - therefore "decoding" it (wrong word, really) via UTF8 will guarantee you corrupt data. The preferred way to deal with protobuf data is as binary - for example, a byte[] - much like you would with image data etc. However, if you are required to store or transport it in a text form, then Convert.ToBase64String and Convert.FromBase64String are appropriate mechanisms to translate between text and binary. Please see the first section of How many ways can you mess up IO? for more information.



来源:https://stackoverflow.com/questions/24611339/using-protobuf-net-i-get-an-exception-about-an-unknown-wire-type-with-listsubc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!