Может ли protobuf-net сериализовать эту комбинацию интерфейса и универсальной коллекции?


Я пытаюсь сериализовать ItemTransaction, и у protobuf-net (r282) возникает проблема.

ItemTransaction : IEnumerable<KeyValuePair<Type, IItemCollection>></code>

И ItemCollection выглядит так:

FooCollection : ItemCollection<Foo>
ItemCollection<T> : BindingList<T>, IItemCollection
IItemCollection : IList<Item>

Где T-производный тип элемента. ItemCollection также имеет свойство типа IItemCollection.

Я сериализуюсь так:

IItemCollection itemCol = someService.Blah(...);
...
SerializeWithLengthPrefix<IItemCollection>(stream, itemCol, PrefixStyle.Base128);

Моя конечная цель-чтобы сериализовать ItemTransaction, но меня зацепил с IItemCollection.

Элемент и его производные типы могут быть [de]сериализованы без проблем, см. [1], но десериализация IItemCollection завершается неудачей (сериализация работает). ItemCollection имеет свойство ItemExpression и при десериализации protobuf не может создать абстрактный класс. Это имеет смысл для меня, но я не уверен, как пройти через это.

ItemExpression<T> : ItemExpression, IItemExpression
ItemExpression : Expression

Выражение item является абстрактным, как и выражение

Как заставить это работать должным образом?

Кроме того, я обеспокоен тем, что ItemTransaction потерпит неудачу, так как коллекции Iitem будут отличаться и неизвестны во время компиляции (an ItemTransaction будет иметь FooCollection, BarCollection, FlimCollection, FlamCollection и т. д.).

Чего мне не хватает (Марк) ?

[1] protobuf-net [de]сериализация через границы сборки

1 3

1 ответ:

Я не совсем понимаю весь сценарий; однако Merge можно использовать для передачи конкретного элемента (в том случае, когда вы хотите создать пустой конкретный экземпляр самостоятельно и позволить protobuf-net заполнить свойства).

Если ItemExpression украшен [ProtoInclude(...)] для ожидаемого ItemExpression<T> он должен разрешить десериализацию-абстрактные типы поддерживаются только до тех пор, пока он никогда не найдет, что ему нужно создать один! Смотрите также мой ответ здесь , который показывает это в использовать.

Если вы можете привести пример, который я могу использовать для воспроизведения проблемы, я смогу предоставить дополнительную информацию.

Основываясь на некоторых примерах вне форума, Я думаю, что пришел к выводу, что это поддерживается , но:

  • Если вы просто используете Deserialize..., самая крайняя производная IList<T> будет создана по умолчанию как List<T>; Вы можете обойти это, используя Merge вместо этого, передавая конкретный экземпляр списка по вашему выбору для заполнения
  • все Item, Foo, Bar должны быть помечены как типы контрактов с соответствующими маркерами наследования между Item и Foo, а также Item и Bar
  • в "v2" (скоро) есть больше контроля для управления конкретными типами списков (и типами элементов для нетипизированных списков)
  • похоже, что существует сбой, связанный с десериализацией списка, где указанный тип элемента не является корневым типом. Это, похоже, было исправлено автоматически в "v2", но мне нужно прогнать его (это, к сожалению, касается обертки "WithLengthPrefix" / список крайних методов, над которыми я все еще работаю)
  • в "v2" вы можете сделать все это, не нуждаясь в атрибутах, если хотите (хотя все еще нужно сказать, как в какой-то момент)

, Но да, он должен работать. Я отправил вам образец по электронной почте и намерен привести в порядок вышеупомянутые внешние методы.