Protobuf网络和流:未设置流时出现InvalidCastException.位置=0

本文关键字:InvalidCastException 位置 设置 网络 Protobuf | 更新日期: 2023-09-27 18:25:51

如果我想用protobuf-net反序列化,为什么我必须手动将序列化对象的流位置设置为0?

我希望protobuf-net总是从一开始就读取我的输入流。

如果我想让protobuf-net从不同的偏移位置读取我的流(比如通过标签读取类或列表的成员),我会认为这将是一个特殊的用例,我必须有意识地以不同的方式处理它(api方式)。

(我的protobuf网络版本是640。)

这是我的测试用例,它使用继承引发了一个异常:

using System.IO;
using ProtoBuf;
namespace ProtobufStreamTest
{
    public class Class1
    {
        static public void Main(string[] args)
        {
            var inheritingModel = new InheritingModel()
            {
                InheritingModelMember1 = "testinheriting",
                BaseModelMember1 = 42,
            };
            var ms = new MemoryStream();
            ProtoBuf.Serializer.Serialize(ms, inheritingModel);
            var originalStreamPos = ms.Position; // == 33
            // ms.Position = 0; // <== works okay, but why do I have to do this? Not setting position = 0 raises InvalidCastException: Unable to cast object of type 'ProtobufStreamTest.BaseModel' to type 'ProtobufStreamTest.InheritingModel'
            var deserialized = ProtoBuf.Serializer.Deserialize<InheritingModel>(ms);
            ms.Close();
        }
    }
    [ProtoContract]
    public class InheritingModel : BaseModel
    {
        [ProtoMember(4)]
        public string InheritingModelMember1 { get; set; }
    }
    [ProtoContract]
    [ProtoInclude(1, typeof(InheritingModel))]
    public class BaseModel
    {
        [ProtoMember(2)]
        public int BaseModelMember1 { get; set; }
    }
}

此测试用例不引发异常,不涉及继承,但反序列化对象具有默认(null)值:

using System.IO;
using ProtoBuf;
namespace ProtobufStreamTest
{
    public class Class1
    {
        static public void Main(string[] args)
        {
            var inheritingModel = new InheritingModel()
            {
                InheritingModelMember1 = "testinheriting",
            };
            var ms = new MemoryStream();
            ProtoBuf.Serializer.Serialize(ms, inheritingModel);
            var originalStreamPos = ms.Position; // == 16
            // ms.Position = 0; // works okay, but why do I have to do this? Not setting position to null results in a deserialized object but with null member values
            var deserialized = ProtoBuf.Serializer.Deserialize<InheritingModel>(ms);
            ms.Close();
        }
    }
    [ProtoContract]
    public class InheritingModel
    {
        [ProtoMember(1)]
        public string InheritingModelMember1 { get; set; }
    }
}

Protobuf网络和流:未设置流时出现InvalidCastException.位置=0

如果我想用protobuf-net反序列化,为什么我必须手动将序列化对象的流位置设置为0?

这是任何接受Stream的API的正常做法;事实上,许多(大多数?)流是不可查找的。自动尝试重置位置是极不寻常的。

我希望protobuf-net总是从一开始就读取我的输入流。如果我想让protobuf-net从不同的偏移位置读取我的流(比如通过标签读取类或列表的成员),我会认为这将是一个特殊的用例,我必须有意识地以不同的方式处理它(api方式)。

我会非常期望。这根本不是Stream的使用方式——与protobuf-net无关,但更多:在一般情况下。尝试使用任何API(序列化、压缩、加密、数据传输等):你会发现几乎所有这些都以相同的方式工作,我认为没有的实现(而是重置位置)是不正确的实现

为什么有两个基本部分:

  • 因为许多流是不可查找的,所以消费者永远不应该认为可以将位置重置为零;它也不应该有两种完全不同的可搜索和不可搜索的行为——因此,唯一表现良好的实现是:不要认为你可以搜索
  • 在许多情况下,一个流被分为多个部分消耗,即它可能是300字节的X,然后是200字节的Y,然后是12字节的Z;当读取Y和Z时,如果流继续重置,将是灾难性的和意外的(即几乎没有API会这样做)

基本上;你的期望不是正常情况。

相关文章:
  • 没有找到相关文章