当试图读取流的末尾时,没有无参数构造函数异常

本文关键字:参数 异常 构造函数 读取 | 更新日期: 2023-09-27 18:02:13

在过去的几个小时里,我一直在与异常'No parameterless constructor found for [type]'作斗争。现在我创建了一个简单的单元测试,它应该反映我在应用程序中得到的内容,并且当我不执行stream.Position = 0时,似乎会抛出此异常。

同样,当对象只是一个标准类(不是从抽象类派生的)时,我不会得到这个异常。

请看下面的代码:

  1. 按原样运行它-它会显示无法找到Base

  2. 的构造函数
  3. 取消流。

  4. 再次注释该行,将派生类更改为不继承基类并取消注释类中唯一的属性,运行它-它不会中断(但显然Name将为null)

有人能解释一下为什么会这样吗?为什么#1抛出(或者为什么#3没有抛出),为什么会出现这个消息?

[Test]
public void CanSerialize_Derived()
{
    var derived = new Derived() {Name = "ngf"};
    var stream = new MemoryStream();
    Serializer.Serialize(stream, derived);
    //stream.Position = 0;
    var deserializedInstance = Serializer.Deserialize<Derived>(stream);
}
[ProtoContract]
[ProtoInclude(9, typeof(Derived))]
public abstract class Base 
{
    [ProtoMember(1)]
    public string Name { get; set; }
}
[ProtoContract]
public class Derived : Base
{
    //[ProtoMember(1)]
    //public string Name { get; set; }
}

当试图读取流的末尾时,没有无参数构造函数异常

长度为0的流在protobuf-net中是有效的;在protobuf-net中,所有的序列化都从DTO继承树的根类型开始,所以它会Base开始——直到它同意数据实际上包含Derived,它才会相信你——并且会尝试使用Base。所以这就是为什么#1扔。

显然,如果您将流留在末尾,则可用于反序列化的数据长度为零。这就是为什么#2通过了。

如果你删除继承,那么继承树的根是Derived;这是一个根本性的变化,但在继承方面的不同之处在于,它不再试图在没有任何信息的情况下反序列化abstract类型。所以这就是为什么#3修复了它(因为不好的原因)。

这里的关键要点是继承是作为信息实现的。除非有相关信息,否则它唯一假定的是该对象是位于继承树根的类型。