Protobuf-net serialization/deserialization Protobuf-net serialization/deserialization arrays arrays

Protobuf-net serialization/deserialization


there's a few different questions here, so I'll answer what I can see: if I've missed anything just let me know.

Firstly, as noted, a MemoryStream is the most common way of getting to a byte[]. This is consistent with most serializers - for example, XmlSerializer, BinaryFormatter and DataContractSerializer also don't have an "as a byte[] overload", but will accept MemoryStream.

Generics: you don't need to use generics; v1 has Serializer.NonGeneric, which wraps this away from you. In v2, the "core" is non-generic, and can be accessed via RuntimeTypeModel.Default; of course Serializer and Serializer.NonGeneric continue to work.

For the issue of having to include the type: yes, the protobuf spec assumes the receiver knows what type of data they are being given. A simple option here is to use a simple wrapper object as the "root" object, with multiple typed properties for the data (only one of which is non-null). Another option might spring from the inbuilt inheritance support via ProtoInclude (note: as an implementation detail, these two approaches are identical).

In your specific example, perhaps consider:

[ProtoContract][ProtoInclude(1, typeof(Message<Foo>))].... More as needed[ProtoInclude(8, typeof(Message<Bar>))]public abstract class Message{   }[ProtoContract]public class Message<T> : Message{    ...}

Then just serialize with <Message> - the API will create the right type automatically.

With recent builds, there is also a DynamicType option that includes type data for you, for example:

[ProtoContract]public class MyRoot {    [ProtoMember(1, DynamicType=true)]    public object Value { get; set; }}

This will work for any Value that holds a contract-type instance (but not for primitives, and ideally not involving inheritance).


The code the OP posted wouldn't quite work for me, the following is a slight adaptation taking onboard a little more of Marc Gravell's suggestions. Inheriting from Message was needed to prevent "Cyclic inheritance is not allowed", and as noted in the code comments below GetBuffer wasn't working out either.

Hoping it helps someone else, took me a good few hours to get it all to work...

      [ProtoContract]      public abstract class Message      {        public byte[] Serialize()        {          byte[] result;          using (var stream = new MemoryStream())          {            Serializer.Serialize(stream, this);            result = stream.ToArray(); //GetBuffer was giving me a Protobuf.ProtoException of "Invalid field in source data: 0" when deserializing          }          return result;        }      }      [ProtoContract]      public class Message : Message      {        [ProtoMember(1)]        public string From { get; private set; }        [ProtoMember(2)]        public string To { get; private set; }        [ProtoMember(3)]        public T MessageBody { get; private set; }        public Message()        { }        public Message(string from, string to, T messageBody)        {          this.From = from;          this.To = to;          this.MessageBody = messageBody;        }        public static Message Deserialize(byte[] message)        {          Message result;          using (var stream = new MemoryStream(message))          {            result = Serializer.Deserialize>(stream);          }          return result;        }      }