Why does the following trivial C# code raise a ProtoException about a missing default constructor?

▼魔方 西西 提交于 2020-01-06 04:40:27

问题


Here is the code:

using System.Diagnostics;
using System.IO;
using ProtoBuf;

namespace ProtoBufTest
{
    [ProtoContract]
    [ProtoInclude(13, typeof(BuildEvent))]
    public abstract class Event
    {
        [ProtoMember(1)]
        public int NodeId { get; set; }
    }

    [ProtoContract]
    public class BuildEvent : Event
    {
    }

    public class Program
    {
        static void Main(string[] args)
        {
            var ms = new MemoryStream();
            Serializer.SerializeWithLengthPrefix<object>(ms, new BuildEvent(), PrefixStyle.Base128);

            Debug.WriteLine(ms.Position);
            ms.Position = 0;

            var ev = Serializer.DeserializeWithLengthPrefix<BuildEvent>(ms, PrefixStyle.Base128);
            Debug.WriteLine(ev.ToString());
        }
    }
}

I am using protobuf-net 2.4.0. Running this code raises the following exception:

Unhandled Exception: ProtoBuf.ProtoException: No parameterless constructor found for ProtoBufTest.Event
   at ProtoBuf.Meta.TypeModel.ThrowCannotCreateInstance(Type type)
   at proto_4(Object , ProtoReader )
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source)
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source)
   at ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source, Object value, Type type, PrefixStyle style, Int32 expectedField, TypeResolver resolver, Int64& bytesRead, Boolean& haveObject, SerializationContext context)
   at ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source, PrefixStyle style, Int32 fieldNumber)
   at ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source, PrefixStyle style)
   at ProtoBufTest.Program.Main(String[] args) in C:\Work\ProtoBufTest\ProtoBufTest\Program.cs:line 30

回答1:


The use of <object> here is incorrect; that's saying "I know the type - the type is object". If you don't have a generic-friendly scenario, you should use the non-generic API - see Serializer.NonGeneric.* or use RuntimeTypeModel.Default.*; this will then obtain the Type via the object.

I will think about whether we should make <object> automatically switch into non-generic mode.



来源:https://stackoverflow.com/questions/52618157/why-does-the-following-trivial-c-sharp-code-raise-a-protoexception-about-a-missi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!