.net 如何序列化继承的属性?

.net 如何序列化继承的属性?,.net,protobuf-net,.net,Protobuf Net,我有一个第三方库,它为一些消息公开了一个抽象类,如下所示 [ProtoContract] public abstract class MessageBase { [ProtoMember(101)] public string ErrorMessage { get; set; } public abstract int Type { get; } } 现在在我的应用程序中,我确实从它创建了一个派生类 [Proto

我有一个第三方库,它为一些消息公开了一个抽象类,如下所示

    [ProtoContract]
    public abstract class MessageBase
    {
        [ProtoMember(101)]
        public string ErrorMessage { get; set; }

        public abstract int Type { get; }
    }
现在在我的应用程序中,我确实从它创建了一个派生类

[ProtoContract]
[ProtoInclude(999, typeof(MessageBase))]
public class Echo : MessageBase
{
    public const int ID = 1;



    public override int Type
    {
        get { return ID; }
    }

    [ProtoMember(1)]
    public string Message { get; set; }
}
但当我尝试(反)/序列化时,基类的属性ErrorMessage被忽略。下面是模拟这种情况的代码

using (MemoryStream ms = new MemoryStream())
            {
                Echo echo = new Echo{Message = "Some message", ErrorMessage = "XXXXX"};
                ProtoBuf.Serializer.Serialize(ms, echo);



                //reset ms
                ms.Seek(0, SeekOrigin.Begin);
                Echo echo1 = (Echo)ProtoBuf.Serializer.NonGeneric.Deserialize(typeof(Echo), ms);
                Debug.Assert(echo.ErrorMessage == echo1.ErrorMessage, "Must be the same");
            } 
我确实读过ProtoInclude,但它似乎在我的派生类中被忽略了

我无法更改基类,我没有第三方库的源代码

我可能有大约100个来自MessageBase的派生类

我必须使用非通用版本的反序列化,因为我只在运行时知道类型

我如何解决我的问题


Thx

您的ProtoIncludeAttribute放错了位置。需要告诉基类型有关派生类型的信息,而不是相反

将ProtoIncludeAttribute添加到MessageBase,并将其从子类中删除(当然,除非子类本身有更多的子类)


如评论中所述;如果无法编辑基类型,则必须在运行时对其进行配置。可以按如下方式进行(另请参见基于注释中的测试):


正如我在消息中所说的,我不能更改基类,我没有它的源代码。但即便如此,如果我有1000个派生类,我应该添加1000个include吗?听起来不太对。@Eugen抱歉,我错过了那部分。在这种情况下,您需要告诉运行时-我将添加一个例子,当我在PC上(现在在移动设备上)-但要强调:是的,这(配置基和从基派生的关系)是正确的-这正是您需要为任何类似的序列化器类别(“基于契约”)所做的,包括XmlSerializer和DataContractSerializer。如果我可以假设:更大的问题是为什么需要1000个子类。这听起来异常高(虽然它仍然可以应付)哦,天哪,这真的很糟糕。我切换到proto而不是JSON来提高速度,结果却遇到了麻烦。json序列化程序从来没有遇到过这样的问题,不知何故,它们知道给定类型的所有属性,包括那些表单基类。无论如何,thx澄清一下,我现在必须切换到另一个序列化程序。我需要1000个类,只是为了使tcp服务器/客户端之间的对话非常类型安全。因此,我有一个消息类用于任何类型的请求/响应。@Eugen推测您的Json序列化程序会添加关于该类型的额外文本。为了提高效率,Protobuf net试图避免这种情况。它确实有一个与此类似的特性,但它目前不能很好地与继承一起工作。如果你“今天”不需要的话,我可以很容易地修复它@eugen-hmm。。。从头开始:即使dymanic类型的功能支持这一点,模型仍然需要以相同的方式配置,这样就不会添加任何内容-可能是为什么我从来没有这样做过!
[Test]
public void AddSubtypeAtRuntime()
{
    var messageBase = RuntimeTypeModel.Default[typeof(MessageBase)];
    // this could be explicit in code, or via some external config file
    // that you process at startup
    messageBase.AddSubType(10, typeof(Echo)); // would need to **reliably** be 10
    messageBase.AddSubType(11, typeof(Foo));
    messageBase.AddSubType(12, typeof(Bar)); // etc

    // test it...
    Echo echo = new Echo { Message = "Some message", ErrorMessage = "XXXXX" };
    MessageBase echo1;
    using (var ms = new MemoryStream())
    {
        Serializer.NonGeneric.Serialize(ms, echo);
        ms.Position = 0;
        echo1 = (MessageBase)Serializer.NonGeneric.Deserialize(
                                   typeof(MessageBase), ms);
    }
    Assert.AreSame(echo.GetType(), echo1.GetType());
    Assert.AreEqual(echo.ErrorMessage, echo1.ErrorMessage);
    Assert.AreEqual(echo.Message, ((Echo)echo1).Message);
}