【问题标题】:Protobuf-net serializationProtobuf-net 序列化
【发布时间】:2014-02-15 07:12:57
【问题描述】:

对于我当前的项目,我正在使用 protobuf-net,但得到了一些奇怪的结果。
我有一个包含两个属性的类:

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

如果我将ID 设置为0,然后输入一个随机的Description,然后检查序列化的byte[],我不会得到预期的结果。

我想用长度前缀序列化类。

我正在像这样对类进行序列化:

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());
}

我期待这样的事情:

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

相反,我得到: 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

开头的这个0x12是什么? 0x00 != 0x12? 我认为我所做的一切都是正确的,但我的代码中可能存在愚蠢的错误吗?

【问题讨论】:

    标签: c# serialization protocol-buffers protobuf-net


    【解决方案1】:

    十六进制 12 是字段头,是二进制 10010。最后 3 位(010)是线路类型:长度前缀。余数 (10) 是字段编号 (2)。所以十六进制 12 表示后面是字段 2,以长度为前缀(在本例中为字符串)。由于 protobuf-net 的隐式零默认行为,字段 1 已被省略。如果需要,您可以通过多种方式强制对字段 1 进行序列化。

    【讨论】:

      【解决方案2】:

      这里是展示如何序列化的示例代码。

      它包括使用ProtoBuf 序列化和反序列化任何类的扩展方法。

      要使用,请包含 NuGet 包protobuf-net(我使用的是版本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; }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-04-26
        • 1970-01-01
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 2021-01-14
        • 2011-09-11
        • 2012-12-18
        相关资源
        最近更新 更多