3

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

另外,当对象只是一个标准类(不是从抽象类派生的)时,在任何情况下我都不会得到这个异常。

请看下面的代码:

  1. 按原样运行它 - 它会中断说找不到 Base 的构造函数

  2. 取消注释 stream.Position = 0 就可以了

  3. 再次注释该行,将 Derived 类更改为不继承自 Base 并取消注释该类中唯一的属性,运行它 - 它不会中断(但显然 Name 将为空)

有人可以解释为什么会这样吗?为什么#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; }
}
4

1 回答 1

5

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

显然,如果您将流放在最后,可反序列化的数据长度为零。这就是为什么#2通过。

如果删除继承,则该继承树的根是Derived; 这是一个根本性的重大变化,但在继承方面的区别在于它不再试图在abstract没有任何信息的情况下反序列化类型。所以这就是#3 修复它的原因(出于不好的原因)。

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

于 2013-03-04T20:08:23.527 回答