用于继承类的Protobuf .NET序列化

时间:2018-06-28 23:22:26

标签: protobuf-net datacontract netdatacontractserializer

我正在尝试将代码序列化程序从NetDataContract迁移到Protobuf.Net。

让我们考虑以下课程示例以帮助理解:

[DataContract(Name "a", IsReference = true)]
class Test
{
    [DataMember(Name = "a")]
    public int Id { get; set; }

    [DataMember(Name = "b")]
    public string Name { get; set; }
}

为了能够通过DataContract使用Protobuf .NET,我使用以下选项:

RuntimeTypeModel.Default.InferTagFromNameDefault = true;            
RuntimeTypeModel.Default.AutoAddProtoContractTypesOnly = false;

使用这些选项,上面显示的示例的序列化有效,但是当添加它的继承时,复杂度会增加。让我们通过此类改进我们的示例:

[DataContract(Name = "b", IsReference = true)]
class InheritanceTest : Test
{
    [DataMember(Name = "c")]
    public string Text { get; set; }
}

现在,要能够序列化从“ Test”继承的类“ InheritanceTest”,我必须添加ProtoInclude参数(已经尝试仅使用KnownType,但它不起作用)。类“测试”的属性应如下所示:

[DataContract(Name "a", IsReference = true)]
[KnownType(typeof(InheritanceTest)]
[ProtoInclude(<TAG>, typeof(InheritanceTest)]
class Test { ... }

恕我直言,复杂性是您必须在“ TAG”中填充未自动从成员(DataMembers)自动分配的订单中使用的数字时。在此示例中,如果我使用TAG = 1,则由于属性ID已使用它而导致错误。 TAG = 2和属性名称相同。所以我需要至少放3个。

这没关系,因为此类太简单了,但是当该类具有多个属性时该怎么办?而且,每当我向其添加属性时,都应该更改TAG吗?似乎维护很糟糕。

我该如何以更简单的方式进行操作?我想念什么吗?

考虑到它是自动分配的,应该只进行一次并缓存。更好的是,应该在编译时完成。

此外...为什么我不能使用[KnownType]属性,而序列化程序却根据定义的类类型的DataContract的名称自动分配TAG?请注意,使用名称自动分配订单的DataMember也会发生类似的情况。

1 个答案:

答案 0 :(得分:0)

  

,但是当添加它的继承时,复杂度会增加。

是的。

  

添加属性后,是否应该更改TAG?

您应该从不更改标签。曾经。

  

维护似乎很糟糕。

完全正确。

  

考虑到它是自动分配的,应该只进行一次并缓存。

是在运行时。

  

更好的是,它应该在编译时完成。

好吧,我不是在关注“推断”方面,而是一般,这是我与编译器团队正在进行的讨论。

  

我想念什么吗?

我是这样认为的;特别是,永远将要更改的模型上不应使用“按名称推断”选项。添加该选项是为了在现有的固定模型上使事情正常工作的务实方式,但是它非常脆弱-在许多方面都很危险。关于您的理解,应该出现 警告,但坦率地说,推荐选项是:始终明确。将[ProtoMember(42)](或其他内容)添加到每个属性。这样就没有猜测,也没有增加破坏成员的新成员的风险。您可以看到所有内容,也可以了解所有内容。