protobuf-net 序列化为基类
Posted
技术标签:
【中文标题】protobuf-net 序列化为基类【英文标题】:protobuf-net Serializing as base class 【发布时间】:2011-10-25 04:24:49 【问题描述】:我想使用 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
显式添加字段。
【问题讨论】:
【参考方案1】:如果您的层次结构不是太复杂,您可以考虑使用序列化成员组合派生类型,而不是从其继承。
[ProtoContract] class Generic
[ProtoMember(1)] public string PublicInfo get; set;
class Specialized
public Generic Generic get; set;
public string SecretInfo get; set;
对象的某些部分是可序列化的,而某些部分是序列化不知道的。将这些混合在一个继承层次结构中并不是一个好主意。因为它不遵循专门化的OO概念。基类是可序列化的,派生类不是,但是为了继承,派生类必须支持基类已经支持的所有内容。
【讨论】:
【参考方案2】:大多数序列化程序会对此感到窒息,因为它们设计是为了让您重现您开始时的内容。相关问题中提出的答案足够,但有点小技巧,因此确实需要RuntimeTypeModel
的一点巫术。在这方面,我非常喜欢DonAndre's answer 中的解决方案,它可以保持一切都非常干净(Specialized
甚至可以是合同,包括Generic
,省略SecretInfo
)。
唯一要做的事情是说服它你的Derived
实际上是一个代理。代理检测代码目前无法在运行时自定义,但不难欺骗它(滥用一些实现知识),即
namespace NHibernate.Proxy
internal interface INHibernateProxy // pretty spectacularly evil
...
class Derived : Base, INHibernateProxy
现在,当它发现它无法识别 Derived
时,它应该检查常见的 proxy 模式,发现它看起来很像 NHibernate 代理,并使用基本类型。真的很可怕而且很邋遢。
【讨论】:
以上是关于protobuf-net 序列化为基类的主要内容,如果未能解决你的问题,请参考以下文章
Protobuf-net RuntimeTypeModel 不序列化基类的成员