protobuf-net序列化为基类

时间:2011-10-25 04:24:49

标签: inheritance protobuf-net

我想使用protobuf-net将派生类序列化为其基类。换句话说,我希望序列化过程丢弃任何类型派生的指示:

[ProtoContract]
class Base
{
    [ProtoMember(1)]
    public string PublicInfo { get; set; }
}

class Derived : Base
{
    public string SecretInfo { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Derived d = new Derived()
        {
            PublicInfo = "public info",
            SecretInfo = "secret info"
        };
        using (var ms = new MemoryStream())
        {
            Serializer.NonGeneric.Serialize(ms, d as Base);
            ms.Seek(0, SeekOrigin.Begin);
            Base deserialized = Serializer.Deserialize<Base>(ms);
            Console.WriteLine("Deserialized type: " + deserialized.GetType());
            Console.WriteLine("Deserialized value: " + deserialized.PublicInfo);
        }
        Console.ReadLine();
    }
}

我想要上面的程序来制作

 Deserialized type: Base
 Deserialized value: public info

但我得到一个关于“不期望类型”的例外。

如果我将[ProtoContract]添加到Derived,则不会设置PublicInfo字段。如果我还将[ProtoInclude(2, typeof(Derived))]添加到Base,则反序列化类型为Derived,而不是Base

我错过了什么?如果我在其他地方忽略了答案,请道歉。我想我要求的是与this question相反的内容,但我不想通过RuntimeTypeModel明确添加字段。

2 个答案:

答案 0 :(得分:4)

如果您的层次结构不是太复杂,您可以考虑使用序列化成员来编写派生类型,而不是继承它。

[ProtoContract] class Generic {
  [ProtoMember(1)] public string PublicInfo { get; set; }
}

class Specialized {
   public Generic Generic { get; set; }
   public string SecretInfo { get; set; }
}

您的对象的某些部分是可序列化的,而某些部分是序列化未发现的。在一个继承层次结构中混合使用它们并不是一个好主意。因为它不遵循专业化的OO概念。基类是可序列化的,派生类不是,但是对于继承,派生类必须支持基类已经支持的所有内容。

答案 1 :(得分:3)

大多数序列化程序会阻塞它,因为它们是设计的,希望允许您重现您的开始。相关问题中提出的答案足够,但有点像黑客,因此 需要RuntimeTypeModel的小巫术。在这方面,我非常喜欢DonAndre's answer中的解决方案,它可以保持一切非常干净(Specialized甚至可以是合同,其中包含Generic并省略SecretInfo

要做的唯一其他事情就是说服你的Derived实际上是代理。代理检测代码目前无法在运行时进行定制,但是不容易欺骗它(滥用一些实施知识),即

namespace NHibernate.Proxy {
    internal interface INHibernateProxy {} // pretty spectacularly evil
}
...
class Derived : Base, INHibernateProxy {}

现在,当它发现它无法识别Derived时,它应检查常见的代理模式,发现它看起来很像NHibernate代理,并使用基类型。非常恐怖和蹩脚。