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-net反序列化,为什么我必须手动将序列化对象的流位置设置为0?
这是任何接受Stream
的API的正常做法;事实上,许多(大多数?)流是不可查找的。自动尝试重置位置是极不寻常的。
我希望protobuf-net总是从一开始就读取我的输入流。如果我想让protobuf-net从不同的偏移位置读取我的流(比如通过标签读取类或列表的成员),我会认为这将是一个特殊的用例,我必须有意识地以不同的方式处理它(api方式)。
我会非常不期望。这根本不是Stream
的使用方式——与protobuf-net无关,但更多:在一般情况下。尝试使用任何API(序列化、压缩、加密、数据传输等):你会发现几乎所有这些都以相同的方式工作,我认为没有的实现(而是重置位置)是不正确的实现。
为什么有两个基本部分:
- 因为许多流是不可查找的,所以消费者永远不应该认为可以将位置重置为零;它也不应该有两种完全不同的可搜索和不可搜索的行为——因此,唯一表现良好的实现是:不要认为你可以搜索
- 在许多情况下,一个流被分为多个部分消耗,即它可能是300字节的X,然后是200字节的Y,然后是12字节的Z;当读取Y和Z时,如果流继续重置,将是灾难性的和意外的(即几乎没有API会这样做)
基本上;你的期望不是正常情况。