ios - Usando Protobuf-net, recibo una excepción sobre un tipo de cable desconocido con List<Subclassable>
unity3d (1)
Empecé a convertir nuestro juego Unity / iOS para guardar el estado con Protobuf-net. Parecía que las cosas funcionaban bien, hasta que agregué esta variable de instancia a GameState
[ProtoMember(10)]
public List<Unit> fUnits;
La unidad es
[ProtoContract]
[ProtoInclude(21, typeof(ArtilleryUnit))]
[ProtoInclude(22, typeof(CavalryArtilleryUnit))]
[ProtoInclude(23, typeof(CavalryUnit))]
[ProtoInclude(24, typeof(InfantryUnit))]
[Serializable]
public class Unit : IActionHandler
Esta es la primera subclase que he serializado. Estoy probando mi código deserializando justo después de escribir
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));
}
y obtengo
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
No hace falta decir que he verificado la sobrescritura (es un archivo completamente nuevo). Y, si saco el ProtoMember(10)
, no lanzará.
Si ProtoInclude
líneas de ProtoInclude
, ProtoInclude
un error sobre las subclases. Y, si saco ProtoMember
dentro de la Unit
, aún arroja.
Si es importante, actualmente solo estoy ejecutando esto desde Xamarin (en Mac OS X, soy desarrollador de iOS). Pero solo por la facilidad de las pruebas, he logrado presionar Protobuf-net con suficientes palos para hacerlo funcionar en un iPad.
Mi mirada se dirige inmediatamente a:
byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
Los datos de Protobuf no son texto , y no son UTF-8 (aunque las cadenas dentro de los datos de protobuf son UTF-8, por coincidencia); por lo tanto, "descifrarlo" (palabra incorrecta, en realidad) a través de UTF8
le garantizará datos corruptos. La forma preferida de tratar con los datos de protobuf es como binario, por ejemplo, un byte[]
- muy parecido a como lo haría con los datos de imagen, etc. Sin embargo, si se le requiere almacenarlo o transportarlo en forma de texto, entonces Convert.ToBase64String
y Convert.FromBase64String
son mecanismos apropiados para traducir entre texto y binario. Por favor, consulte la primera sección de ¿De cuántas maneras puede estropear IO? para más información.