我正在尝试将代码序列化程序从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也会发生类似的情况。
答案 0 :(得分:0)
,但是当添加它的继承时,复杂度会增加。
是的。
添加属性后,是否应该更改TAG?
您应该从不更改标签。曾经。
维护似乎很糟糕。
完全正确。
考虑到它是自动分配的,应该只进行一次并缓存。
是在运行时。
更好的是,它应该在编译时完成。
好吧,我不是在关注“推断”方面,而是一般,这是我与编译器团队正在进行的讨论。
我想念什么吗?
我是这样认为的;特别是,永远将要更改的模型上不应使用“按名称推断”选项。添加该选项是为了在现有的固定模型上使事情正常工作的务实方式,但是它非常脆弱-在许多方面都很危险。关于您的理解,应该出现 警告,但坦率地说,推荐选项是:始终明确。将[ProtoMember(42)]
(或其他内容)添加到每个属性。这样就没有猜测,也没有增加破坏成员的新成员的风险。您可以看到所有内容,也可以了解所有内容。