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
,而不是 基地
如我所愿。
我缺少什么?如果我忽略了其他地方的答案,请道歉。我想我问的问题与这个问题相反,尽管我不想通过显式添加字段运行时类型模型
。
I'd like to use protobuf-net to serialize a derived class as its base class. In other words, I want the serialization process to discard any indication that the type is derived:
[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();
}
}
I'd like the above program to produce
Deserialized type: Base
Deserialized value: public info
but instead I get an exception about "Type is not expected".
If I add [ProtoContract]
to Derived
, the PublicInfo
field isn't set. And if I also add [ProtoInclude(2, typeof(Derived))]
to Base
then the deserialized type is Derived
, not Base
as I want.
What am I missing? Apologies if I've overlooked an answer somewhere else. I think I'm asking for something like the opposite of this question, though I'd rather not have to explicitly add fields via the RuntimeTypeModel
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您的层次结构不太复杂,您可以考虑使用序列化成员组合派生类型,而不是从中继承。
对象的某些部分是可序列化的,而某些部分是序列化不知道的。将这些混合在一个继承层次结构中并不是一个好主意。因为它不遵循OO的专业化概念。基类是可序列化的,派生类不是,但是对于继承,派生类必须支持基类已经支持的所有内容。
If your hierarchy isn't too complex you could think about composing your derived type with a serialization member instead of inheriting from it.
There are some parts of your object that are serializable and some parts are serialization unaware. It's not a good idea to mix these in one inheritance hierarchy. Because it doesn't follow the OO concept of specialization. The base class is serializable, the derived class not, however for inheritance the derived class would have to support everything that the base class already supports.
大多数序列化器都会对此感到窒息,因为它们被设计就是为了让您重现开始时的内容。相关问题中提出的答案就足够了,但有点破解,因此确实需要使用
RuntimeTypeModel
一点巫毒。在这方面,我非常喜欢 DonAndre 的回答中的解决方案,这使得一切都非常干净(并且Specialized
甚至可以是一个合同,其中包含Generic
和SecretInfo
省略)。唯一要做的事情是让其相信您的
派生
实际上是代理。代理检测代码目前无法在运行时自定义,但是欺骗它并不难(滥用一些实现知识),即现在,当它发现它无法识别
Derived
时应该检查常见的代理模式,发现它看起来很像 NHibernate 代理,并使用基本类型。真的很可怕而且又脏。Most serializers will choke on that, since they are designed to want to allow you to reproduce what you started with. The answer proposed in the related question would suffice, but is a bit of a hack and as such does require a little voodoo with
RuntimeTypeModel
. In that respect, I quite like the solution in DonAndre's answer, which keeps everything pretty clean (andSpecialized
could even be a contract, withGeneric
included andSecretInfo
omitted).The only other thing to do would be to convince it that your
Derived
is actually a proxy. The proxy detection code is not currently customisable at runtime, however it wouldn't be hard to fool it (abusing some knowledge of the implementation), i.e.now, when it finds it doesn't recognise
Derived
it should check for common proxy patterns, find it looks a lot like an NHibernate proxy, and use the base-type. Really horrible and grungy.