【问题标题】:Serialisation with inheritance in protobuf-net在 protobuf-net 中使用继承进行序列化
【发布时间】:2012-10-01 13:18:02
【问题描述】:

给定一个如下所示的 .proto:

message Base {
    string Dummy = 1
}

message Derived {
    Base Super = 1
    string Parp = 2 
}

... 还有一些 C# 类似:

public class Base {
    public string Dummy;
}

public class Derived : Base {
    public string Parp
}

如何在 protobuf-net 中自定义序列化才能做到这一点?最初我开始考虑使用 TypeModel 并为 Base MetaType 调用 AddSubType,但后来它似乎为 Base 创建了类型定义,其中包含所有派生类的可选字段(即相反与我需要的)

我以为我自己可以遍历层次结构,但是查看 TypeModel,它似乎支持将类型提供给 Deserialise,但它在序列化过程中使用 value.GetType()。即便如此,我如何做到这一点也不完全清楚。我唯一的选择是使用 ProtoWriter 手动编写每个字段吗?这是我目前正在尝试的,但我希望有更简单的方法。

【问题讨论】:

    标签: c# serialization protobuf-net


    【解决方案1】:

    首先要注意的是protobuf本身不支持继承。对此没有“官方”布局。 Protobuf-net 不会按照您希望的方式支持序列化:选择子类型封装(而不是基本类型封装)是为了解决几个问题,包括:

    • 满足 Liskov 替换原则
    • 当调用者不知道/预期序列化类型时正常工作
    • 基本上,完全可以工作(除了最简单的例子,两端都提前知道他们得到的是哪个子类型,这在很大程度上违背了多态性的观点)

    但是,您可以手动映射 DTO,基本上这样您的 DTO 层根本不使用继承。

    【讨论】:

    • 谢谢 Marc... 我很感激它不支持它,但是使用这个超级指针的概念(是的,我提前知道我的消息类型),我可以用ProtoReader/Writer?
    • @chrism 这取决于你自己写多少。 ProtoReader/ProtoWriter API 提供了处理有线格式的完全访问权限,但您必须处理所有字段级处理 - 例如,没有 IProtoSerializable 允许控制一种类型。
    • 还有其他建议吗?拥有一组单独的 DTO 我映射到似乎我会做很多分配只是为了将数据复制到对象中以进行序列化/反序列化
    • @chrism “很多”是主观的,取决于场景;此外,作为短命的对象,它们很可能从 gen-0 中收集。我要说的是:如果没有更多上下文(吞吐量等),我们不能说“很多”是否“太多”。但是:您的模型中涉及多少类型(只是试图评估读/写方法中将涉及多少代码)。最后,具体布局有什么要求?如果要匹配另一个非protobuf-net布局,那么我会说:不要使用继承:使用与您所需的线路布局匹配的封装。
    • 一看,每秒 1000 次。正是因为如此,布局就是这样,它集成到一个已经存在的代码库中,其中消息布局使用超级指针。继承的愿望是,例如,XYZRequest 将从 C# 中的 Request 派生,但在网络上,该类型将具有 Request 类型的 Super 字段
    猜你喜欢
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多