BigInteger的Protobuf-net代理类

时间:2017-08-17 08:44:16

标签: c# biginteger protobuf-net

我想在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的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

听起来第二个转换是反序列化期间的初始值,然后这会导致串联的字节数组。一个快速修复可能是在转换运算符中检查零并始终分配空/空字节数组。这将干净地连接起来。但是,“正确”修复可能是在字节数组的ProtoMemberAttibute中添加“覆盖列表”标志 - 这将确保替换内容而不是连接内容。坦率地说,我很想和他们一起做这两件事。