Может ли 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 ответ:
Я не совсем понимаю весь сценарий; однако
Merge
можно использовать для передачи конкретного элемента (в том случае, когда вы хотите создать пустой конкретный экземпляр самостоятельно и позволить protobuf-net заполнить свойства).Если
Если вы можете привести пример, который я могу использовать для воспроизведения проблемы, я смогу предоставить дополнительную информацию.ItemExpression
украшен[ProtoInclude(...)]
для ожидаемогоItemExpression<T>
он должен разрешить десериализацию-абстрактные типы поддерживаются только до тех пор, пока он никогда не найдет, что ему нужно создать один! Смотрите также мой ответ здесь , который показывает это в использовать.
Основываясь на некоторых примерах вне форума, Я думаю, что пришел к выводу, что это поддерживается , но:
- Если вы просто используете
Deserialize...
, самая крайняя производнаяIList<T>
будет создана по умолчанию какList<T>
; Вы можете обойти это, используяMerge
вместо этого, передавая конкретный экземпляр списка по вашему выбору для заполнения- все
Item
,Foo
,Bar
должны быть помечены как типы контрактов с соответствующими маркерами наследования междуItem
иFoo
, а такжеItem
иBar
- в "v2" (скоро) есть больше контроля для управления конкретными типами списков (и типами элементов для нетипизированных списков)
- похоже, что существует сбой, связанный с десериализацией списка, где указанный тип элемента не является корневым типом. Это, похоже, было исправлено автоматически в "v2", но мне нужно прогнать его (это, к сожалению, касается обертки "WithLengthPrefix" / список крайних методов, над которыми я все еще работаю)
- в "v2" вы можете сделать все это, не нуждаясь в атрибутах, если хотите (хотя все еще нужно сказать, как в какой-то момент)
, Но да, он должен работать. Я отправил вам образец по электронной почте и намерен привести в порядок вышеупомянутые внешние методы.