Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Google.ProtocolBuffers Deserialization Method (proto3)

I have recently upgraded my code base (Java, C++ and C#) to use proto3. In the case of C# this has involved over 2000 changes to the code. This is mostly semantic and all good, but there is one issue I can't seem to fathom; serialization/deserialization. I have the following amended method to desearialize my IMessage types (the code to do this in proto2 is commented), this is the code that is show in the examples within the GitHub repository...

public static T ToObject<T>(this byte[] buf) where T : IMessage 
{
    if (buf == null)
        return default(T);

    using (MemoryStream ms = new MemoryStream())
    {
        ms.Write(buf, 0, buf.Length);
        ms.Seek(0, SeekOrigin.Begin);

        MessageParser parser = new MessageParser();
        return (T)parser.ParseFrom(ms);
            //ProtoBuf.Serializer.Deserialize<T>(ms);
    }
}

but the line MessageParser parser = new MessageParser(); is giving me a design/compile-time error

MessageParser does not contain a constructor that contains 0 aguments

Well that is curious as I know about proto3 documents that tell me the contrary.

All I want to know is, using proto3, how I can perform my deserialization?

Thanks for your time.


Note, my serialization code is

public static byte[] ToByteArray<T>(this T o) where T : IMessage 
{
    if (o == null)
        return null;

    using (MemoryStream ms = new MemoryStream())
    {
        o.WriteTo(ms);
        return ms.ToArray();
    }
}

This compiles, but is it right?

like image 412
MoonKnight Avatar asked Feb 11 '16 10:02

MoonKnight


1 Answers

For your deserialization compile time error, the documentation told that you should pass a Func<T> as a function factory to create instances of T to the constructor of MessageParser<T>.

It could be () => new T() or a more complicated function depending on what it needs to create your messages.

Full code:

public static T ToObject<T>(this byte[] buf) where T : IMessage<T>, new()
{
    if (buf == null)
        return default(T);

    using (MemoryStream ms = new MemoryStream())
    {
        ms.Write(buf, 0, buf.Length);
        ms.Seek(0, SeekOrigin.Begin);

        MessageParser<T> parser = new MessageParser<T>(() => new T());
        return parser.ParseFrom(ms);
    }
}

As the documentation says the serialization should be ok.

like image 180
Fab Avatar answered Sep 17 '22 16:09

Fab