2013-03-04 69 views
3

过去几个小时我一直在处理异常'No parameterless constructor found for [type]'。现在我创建了一个简单的单元测试,它应该能够反映我在应用程序中获得的结果,并且当我不执行stream.Position = 0时,似乎会抛出此异常。尝试读取数据流结尾时没有无参数构造函数异常

此外,当对象只是一个标准类(不是从抽象派生而来)时,我不会得到这个异常。

请参见下面的代码:

  1. 运行它是 - 它会破坏说,没有构造可以为基地

    找到
  2. 取消注释stream.Position = 0,这将是罚款

  3. 再次注释掉该行,将Derived类更改为不从Base继承,并取消注释类中的唯一属性,运行它 - 它不会中断(但显然该名称将为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; } 
} 

回答

5

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

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

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

这里的关键是继承作为信息实施。除非有信息,否则它假设的唯一事情是该对象是继承树根部的类型。

+0

感谢您的解释 - 行为现在确实更有意义。 – 2013-03-04 20:25:03

相关问题