我想在BigInteger值上使用protobuf-net。 所以,我写代理类,测试并得到结果
这是测试的来源:
using ProtoBuf;
using System;
using System.Numerics;
namespace BigIntegerSurrogate
{
[ProtoContract]
public class AA
{
[ProtoMember(1)]
public BigInteger Bi { get; set; }
}
[ProtoContract]
public class BigIntegerSurrogate
{
[ProtoMember(1)]
public byte[] BigIntegerBytes;
[ProtoConverter]
public static BigIntegerSurrogate Convert(BigInteger source)
{
var t = source.ToByteArray();
Console.WriteLine($"Convert from Source: {source.ToString()} => [{string.Join(",", t)}]");
return new BigIntegerSurrogate
{
BigIntegerBytes = t
};
}
[ProtoConverter]
public static BigInteger Convert(BigIntegerSurrogate surrogate)
{
if (surrogate == null || surrogate.BigIntegerBytes == null)
{
return BigInteger.Zero;
}
else
{
var bi = new BigInteger(surrogate.BigIntegerBytes);
Console.WriteLine($"Convert from Bytes: [{string.Join(",", surrogate.BigIntegerBytes)}] => {bi.ToString()}");
return bi;
}
}
}
class Program
{
static void Main(string[] args)
{
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
//model.Add(typeof(BigInteger), true);
model.Add(typeof(BigInteger), false).SetSurrogate(typeof(BigIntegerSurrogate));
var aa = new AA() { Bi = 100 };
byte[] aaSerialized;
using (var stream = new System.IO.MemoryStream())
{
Serializer.Serialize(stream, aa);
aaSerialized = stream.ToArray();
}
AA aa2;
using (var stream = new System.IO.MemoryStream(aaSerialized))
{
aa2 = Serializer.Deserialize<AA>(stream);
}
Console.WriteLine($"{aa2.Bi.ToString()}");
}
}
}
结果是:
Convert from Source: 100 => [100]
Convert from Source: 0 => [0]
Convert from Bytes: [0,100] => 25600
首先,protobuf调用期望值(= 100),但它再次调用未知零。
它在反序列化时使用100和0的连续数组调用convert()。 所以,结果值是错误的。
我有什么不对吗?如果是这样,用二进制格式(de)序列化BigInteger的正确方法是什么?
答案 0 :(得分:0)
听起来第二个转换是反序列化期间的初始值,然后这会导致串联的字节数组。一个快速修复可能是在转换运算符中检查零并始终分配空/空字节数组。这将干净地连接起来。但是,“正确”修复可能是在字节数组的ProtoMemberAttibute
中添加“覆盖列表”标志 - 这将确保替换内容而不是连接内容。坦率地说,我很想和他们一起做这两件事。