我在一个大型项目中更新了一个旧版本的protobuf到当前的版本(使用的版本大约是1-2年前)。我不认识牧师)。可悲的是,较新的版本会引发异常。
CreateWireTypeException在ProtoReader.cs第292行
在以下测试用例中:
enum Test
{
test1 = 0,
test2
};
static public void Test1()
{
Test original = Test.test2;
using (MemoryStream ms = new MemoryStream())
{
Serializer.SerializeWithLengthPrefix<Test>(ms, original, PrefixStyle.Fixed32, 1);
ms.Position = 0;
Test obj;
obj = Serializer.DeserializeWithLengthPrefix<Test>(ms, PrefixStyle.Fixed32);
}
}我发现枚举不应该直接在类之外序列化,但是我们的系统太大了,不能简单地将所有枚举封装在类中。对这个问题还有什么其他的解决办法吗?它只适用于序列化和反序列化(只有DeserializeWithLengthPrefix抛出异常)。
该测试用例在旧版本(如protobuf的r262 )中运行良好。
发布于 2013-05-29 07:28:56
简单地说,是一个bug;这是在r640中修复的(现在已经部署到NuGet和google中了),以及基于上面代码的附加测试,这样它就不会重新出现。
关于性能(注释);我要看的第一个提示是:“偏好组”。基本上,protobuf规范包含了包含子对象的两种不同方式--“组”和“长度-前缀”。组是最初的实现,但谷歌现在已经转向“长度前缀”,并试图建议人们不要使用“组”。不过!由于protobuf的工作原理,“组”的编写成本实际上要低得多;这是因为与google的实现不同,不是事先就知道事情的长度。这意味着要写入长度前缀,它需要执行以下操作之一:
我已经在不同的时间实现了所有三种方法,但是v2使用了第三种方法。我一直在玩添加第四个实现:
但是..。大家的共识似乎是,“超长形式”有一点风险;不过,对于protobuf来说,它会很好地工作。
但是正如你所看到的:长度前缀总是有一些开销。现在,想象一下相当深层次的嵌套对象,您可以看到一些亮点。组的工作方式非常不同;组的编码格式是:
就是这样;不需要长度;写起来真的,真的,非常便宜。在导线上,它们之间的主要区别是:
但!太多细节了!
这对你意味着什么?想象一下你有:
[ProtoContract]
public class SomeWrapper
{
[ProtoMember(1)]
public List<Person> People { get { return people; } }
private readonly List<Person> people = new List<Person>();
}您可以进行非常复杂的更改:
[ProtoContract]
public class SomeWrapper
{
[ProtoMember(1, DataFormat=DataFormat.Group)]
public List<Person> People { get { return people; } }
private readonly List<Person> people = new List<Person>();
}它会使用更便宜的编码方案。只要您使用的是protobuf,所有现有的数据都会很好。
https://stackoverflow.com/questions/16803233
复制相似问题