我在一个巨大的项目中将旧版本的protobuf更新为当前版本(使用的版本大约是1-2岁。我不知道转速)。 可悲的是,新版本引发了异常
ProtoReader.cs第292行中的CreateWireTypeException
在以下测试用例中:
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-net的r262。
答案 0 :(得分:3)
简单地说,一个bug;这已在r640中修复(现在部署到NuGet和谷歌代码),以及基于上面代码的额外测试,以便它不会再回来。
表现(评论);我想看的第一个提示是:“偏好群组”。基本上,protobuf规范包括两种不同的方式来包括子对象 - “组”和“长度前缀”。群组是原始实施,但谷歌现在已经转向“长度前缀”,并试图建议人们不要使用“群组”。然而!由于protobuf-net的运作方式,“群体”的写作实际上要便宜得多;这是因为与谷歌实施不同,protobuf-net确实不知道事情的长度。这意味着要编写长度前缀,需要执行以下操作之一:
我在不同时间实现了所有3种方法,但v2使用了第3种方法。我一直在努力添加第四个实现:
但是你可以看到:length-prefix总是有一些开销。现在想象一下相当深的嵌套对象,你可以看到一些blips。小组的工作方式不同;组的编码格式为:
就是这样;不需要长度;写真的,真的,真的很便宜。在电线上,它们之间的主要区别是:
但是!太详细了!
这对你意味着什么?好吧,想象你有:
[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-net,所有现有数据都可以。