BigInteger 的 Protobuf-net 代理 class
Protobuf-net surrogate class for BigInteger
我想要 BigInteger 值上的 protobuf-net。
所以,我写代理class,测试并得到结果
这是测试源:
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),但它再次调用未知零。
并且它在反序列化时调用 convert() 与 100 和 0 的串联数组。
所以,结果值是错误的。
我是不是有什么问题?如果是这样,用二进制格式(反)序列化 BigInteger 的正确方法是什么?
听起来第二个convert是反序列化时的初始值,这导致了一个串联的字节数组。一种快速修复可能是检查转换运算符中的零并始终分配一个 null/empty 字节数组。这将干净地连接起来。但是,"correct" 修复可能是在字节数组的 ProtoMemberAttibute
中添加 "overwrite list" 标志 - 这将确保替换而不是连接内容。坦率地说,我很想同时做这两件事。
我想要 BigInteger 值上的 protobuf-net。 所以,我写代理class,测试并得到结果
这是测试源:
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),但它再次调用未知零。
并且它在反序列化时调用 convert() 与 100 和 0 的串联数组。 所以,结果值是错误的。
我是不是有什么问题?如果是这样,用二进制格式(反)序列化 BigInteger 的正确方法是什么?
听起来第二个convert是反序列化时的初始值,这导致了一个串联的字节数组。一种快速修复可能是检查转换运算符中的零并始终分配一个 null/empty 字节数组。这将干净地连接起来。但是,"correct" 修复可能是在字节数组的 ProtoMemberAttibute
中添加 "overwrite list" 标志 - 这将确保替换而不是连接内容。坦率地说,我很想同时做这两件事。