使用Protobuf-net实现抽象类的序列化和应对对象



背景

我正在尝试获取以下类以序列化和划分使用Protobuf-net实现抽象类的类。但是,它在与错误进行挑选时失败:"找不到抽象测试的无参数构造函数"。

我在做什么错误?

我尝试过的

我花了很多时间研究答案,但是很少有问题涉及我问题的抽象性质。

最小示例

    public class TestRunner
    {
        public void Go()
        {
            string encoded = Serialize<ConcreteTest>(new ConcreteTest());
            object ob = Deserialize(new System.IO.MemoryStream(Encoding.ASCII.GetBytes(encoded)));
        }
        public static string Serialize<T>(T data)
        {
            MemoryStream outputStream = new MemoryStream();
            Serializer.Serialize<T>(outputStream, data);
            outputStream.Position = 0;
            StreamReader outputReader = new StreamReader(outputStream);
            return outputReader.ReadToEnd();
        }
        public static object Deserialize(Stream data)
        {
             AbstractTest test = Serializer.Deserialize<AbstractTest>(data);
             //Error from the line above: No parameterless constructor found for AbstractTest
            if (test.ID == 3)
            {
                 return Serializer.Deserialize<ConcreteTest>(data);
            }
            throw new Exception("We don't know how to handle the message type if I got here!");
        }
    }

[ProtoBuf.ProtoContract]
[ProtoBuf.ProtoInclude(25, typeof(ConcreteTest))]
public abstract class AbstractTest
{
    public AbstractTest()
    {
    }
    [ProtoBuf.ProtoMember(1)]
    public int ID = 3;
    public abstract void Test();
}

[ProtoBuf.ProtoContract]
public class ConcreteTest : AbstractTest
{
    [ProtoBuf.ProtoMember(2)]
    public int ID2 = 4;
    public override void Test()
    {
         MasterLog.DebugWriteLine("It worked!");
    }
}

最初的问题是您通过向后使用Encoding损坏数据。Encoding将任意文本转换为格式化的二进制文本(含义:根据该"编码"的规则格式化(,并将格式化的二进制重新返回到任意文本。它旨在描述如何将文本写入流。您已经向后使用了它,含义:您已经使用它以不同的格式将任意二进制转换为字符串。您可能实际上使用了两个不同的编码(默认情况下,StreamReader几乎不会使用ASCII(。

so:您不能在此处使用Encoding。您的 can 使用是base-64;例如:

using (var outputStream = new MemoryStream())
{
    Serializer.Serialize<T>(outputStream, data);
    return Convert.ToBase64String(outputStream.GetBuffer(),
        0, (int)outputStream.Length);
}

您可以使用Convert.FromBase64String

将其逆转
using (var ms = new System.IO.MemoryStream(Convert.FromBase64String(encoded)))
{
    object ob = Deserialize(ms);
    Console.WriteLine(ob.ToString());
}

也存在一个问题,您可以在不倒带的情况下进行两次测试,这意味着第二个值得在零字节上工作,这意味着它 will 尝试实例化抽象类型;因此,您还需要修复Deserialize方法:

public static object Deserialize(Stream data)
{
    AbstractTest test = Serializer.Deserialize<AbstractTest>(data);
    return test;
}

完成此操作,一切都可以正常工作。

最新更新