1

我正在尝试将我的代码序列化程序从 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 { ... }

恕我直言,复杂性在于您必须使用成员(DataMembers)自动分配的订单中未自动使用的数字填充“标签”。在此示例中,如果我使用 TAG=1 则会出错,因为属性 Id 已经使用它。与 TAG=2 和属性名称相同。所以我至少需要放3个。

没关系,因为这个类太简单了,但是当这个类有几个属性时我该怎么办?每当我向其添加属性时,我是否应该更改 TAG?维护起来似乎很糟糕。

我怎样才能以更简单的方式做到这一点?我错过了什么吗?

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

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

4

1 回答 1

0

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

是的,它确实。

每当我向其添加属性时,我是否应该更改 TAG?

永远不应该更改标签。曾经。

维护起来似乎很糟糕。

确切地。

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

它是,在运行时。

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

好吧,我并不关注“推断”方面,但总的来说,这是我与编译器团队正在进行的讨论。

我错过了什么吗?

我想是的,是的;特别是,您应该在将要更改的模型上使用“按名称推断”选项。该选项被添加为一种实用的方式,可以让事情在现有的固定模型上运行,但它非常脆弱 - 并且在许多方面很危险。您的智能感知中应该会出现关于此的警告,但坦率地说,推荐的选项是:始终明确。添加(或其他)到每个属性。然后就没有猜测,也没有添加破坏事物的新成员的风险。你可以看到一切,你可以理解一切。[ProtoMember(42)]

于 2018-06-28T23:39:51.827 回答