Я пытаюсь перенести сериализатор кода из 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; }
}
Чтобы использовать Protobuf .NET с использованием DataContract, я использую следующие опции:
RuntimeTypeModel.Default.InferTagFromNameDefault = true;
RuntimeTypeModel.Default.AutoAddProtoContractTypesOnly = false;
Используя эти опции, сериализация показанного выше примера работает, но при добавлении наследования его сложность возрастает. Давайте улучшим наш пример с этим классом:
[DataContract(Name = "b", IsReference = true)]
class InheritanceTest : Test
{
[DataMember(Name = "c")]
public string Text { get; set; }
}
Теперь, чтобы иметь возможность сериализовать класс "InheritanceTest", который наследуется от "Test", я должен добавить параметр ProtoInclude (уже пытался использовать только KnownType, но он не работал). Атрибуты класса «Тест» должны быть такими:
[DataContract(Name "a", IsReference = true)]
[KnownType(typeof(InheritanceTest)]
[ProtoInclude(<TAG>, typeof(InheritanceTest)]
class Test { ... }
Сложность ИМХО заключается в том, что вам нужно заполнить «TAG» номером, который не используется автоматически из автоматически назначенного заказа членов (DataMembers). В этом примере, если я использую TAG = 1, он получает ошибку, потому что свойство Id уже использует его. То же самое с TAG = 2 и именем свойства. Поэтому мне нужно поставить как минимум 3.
Это нормально, так как этот класс слишком прост, но что мне делать, если у класса есть несколько свойств? И должен ли я менять тег при добавлении к нему свойства? Кажется ужасным для обслуживания.
Как я могу сделать это проще? Я что-то упустил?
Учитывая, что он назначается автоматически, его следует выполнить только один раз и кэшировать. Еще лучше, это должно быть сделано во время компиляции.
Дополнительно ... почему я не могу использовать атрибут [KnownType], и сериализатор автоматически назначает TAG на основе имени DataContract определенного класса? Обратите внимание, что нечто подобное происходит с DataMember, использующим имя для автоматического назначения заказа.