Protobuf-net não serializando Lista

Sep 29 2020

Atualmente, estou experimentando com protobuf-net (v3.0.29) e tentando serializar / desserializar algumas classes simples. A partir do exemplo de trabalho mínimo, não entendo por que protobuf-net serializa / desserializa o simples List<int> Valuepara uma lista sem elementos.

    public enum BigEnum { One, Two }

    [ProtoContract]
    public class Container
    {
        [ProtoMember(1)]
        public BigEnum Parameter { get; private set; }
        [ProtoMember(2)]
        public List<int> Value { get; set; }
        public Container()
        {
            Parameter = BigEnum.One;
            Value = new List<int>();
        }
    }
    static class Program
    {
        static void Main(string[] args)
        {
            Container data = new Container();
            data.Value.Add(-1);
            data.Value.Add(1);

            MemoryStream memStream = new MemoryStream();
            Serializer.Serialize<Container>(memStream, data);
            var result = Serializer.Deserialize<Container>(memStream);
        }
    }

Este arquivo protobuf foi gerado por Serializer.GetProto () e parece bom para mim. Como podemos processar List<int> Valuecorretamente e pode protobuf-net lidar com estruturas mais complexas como List<KeyValuePair<String, String>>ou Dictionary<int,double>dentro de uma classe? Existem alguns posts muito antigos para protobuf-net com dicionários por aí, mas eu não sei qual é o estado atual.

syntax = "proto3";
package NetCoreProtobuf;

enum BigEnum {
   One = 0;
   Two = 1;
}
message Container {
   BigEnum Parameter = 1;
   repeated int32 Value = 2 [packed = false];
}

Respostas

1 MarcGravell Sep 28 2020 at 23:18

Muito simples: você não rebobinou o fluxo, então ele leu da posição atual - no final do fluxo, com zero bytes para ler. Acontece que o byte zero é perfeitamente válido no protobuf, então ele não pode realmente gerar uma exceção aqui, já que você pode estar totalmente correto ao desserializar o byte zero.

Serializer.Serialize<Container>(memStream, data);
memStream.Position = 0;
var result = Serializer.Deserialize<Container>(memStream);

Ou mais simples: use o DeepClonemétodo:

var clone = Serializer.DeepClone(data);