문제

for my current project I'm working with protobuf-net and I got some weird results.
I have a class that contains two properties:

[ProtoContract]
class MyClass{
    [ProtoMember(1)]
    public int ID { get; set; }
    [ProtoMember(2)]
    public string Description { get; set; }
}

If I set ID to 0 and enter a random Description and check the serialized byte[] afterwards, I don't get the expected result.

I would like to serialize the class with a length prefix.

I'm serializing the class like this:

var myclass = new MyClass()
{
    ID = 0, Description = "ThisIsAShortDescription"
};

using(var stream = new MemoryStream())
{
    Serializer.SerializeWithLengthPrefix<MyClass>(stream, myclass, PrefixStyle.Base128);

    Console.WriteLine(BitConverter.ToString(stream.GetBuffer());
}

I'm expecting something like this:

19 00 17 54 68 69 73 49 73 41 53 68 6f 72 74 44 65 73 63 72 69 70 74 69 6f 6e
19 -> length of the packet
00 -> ID
17 -> length of following string
rest -> string

Instead I'm getting: 19 12 17 54 68 69 73 49 73 41 53 68 6f 72 74 44 65 73 63 72 69 70 74 69 6f 6e

What is this 0x12 at the beginning? 0x00 != 0x12? I think that I've done anything right but is there maybe a silly bug in my code?

도움이 되었습니까?

해결책

Hex 12 is the field header, and is binary 10010. The last 3 bits (010) is the wire type: length-prefixed. The remainder (10) is the field number (2). So the hex 12 is indicating that what follows is field 2, length-prefixed (in this case, a string). Field 1 has been omitted due to protobuf-net's implicit zero default behavior. You can force field 1 to be serialized in a number of ways if you need to.

다른 팁

Here is sample code showing how to serialize.

It includes extension methods to serialize and deserialize any class using ProtoBuf.

To use, include the NuGet package protobuf-net (I used version 2.0.0.668).

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;

namespace Protobuf_Net
{
    class Program
    {
        static void Main(string[] args)
        {
            MyMessage original = new MyMessage(42, "Bob");

            byte[] rawBytes = original.ProtoBufSerialize<MyMessage>();

            MyMessage deserialized = rawBytes.ProtoBufDeserialize<MyMessage>();

            Console.WriteLine("Num={0}", deserialized.Num);
            Console.WriteLine("Name={0}", deserialized.Name);
            Console.Write("[any key]");
            Console.ReadKey();
        }
    }
}

public static class ProtoBufExtensions
{
    // Intent: serializes any class to a byte[] array.
    public static byte[] ProtoBufSerialize<T>(this T message)
    {
        byte[] result;
        using (var stream = new MemoryStream())
        {
            Serializer.Serialize(stream, message);
            result = stream.ToArray();
        }
        return result;
    }

    // Intent: deserializes any class from a byte[] array.
    public static T ProtoBufDeserialize<T>(this byte[] bytes)
    {
        T result;
        using (var stream = new MemoryStream(bytes))
        {
            result = Serializer.Deserialize<T>(stream);
        }
        return result;
    }
}

[ProtoContract]
public struct MyMessage
{
public MyMessage(int num, string name)
{
    Num = num;
    Name = name;
}

[ProtoMember(1)]
public int Num { get; set; }

[ProtoMember(2)]
public string Name { get; set; }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top