protobuf-net Как избежать сбоев при работе с индексированными свойствами
Я пытаюсь интегрировать удивительную protobuf-сеть в существующую кодовую базу, но сталкиваюсь с падением, когда он пытается обработать пользовательский тип. Ниже приведена небольшая демонстрация: InvalidOperationException
в ProtoBuf.Serializers.ListDecorator
, Но если вы закомментируете индексатор (или удалите реализацию IEnumerable), он будет работать без ошибок.
using System.Collections.Generic;
using ProtoBuf;
using System.Collections;
[ProtoContract]
public class MyClass : IEnumerable<int>
{
[ProtoMember(1, IsPacked = true)]
public int[] data { get; set; }
// Comment out this indexed property to prevent the crash
public int this[int i] { get { return data[i]; } set { data[i] = value; } }
public IEnumerator<int> GetEnumerator() { foreach (var x in data) yield return x; }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
static void Main(string[] args) { Serializer.PrepareSerializer<MyClass>(); }
}
Я делаю что-то неправильно? Как я могу сказать Serializer protobuf-net просто игнорировать это свойство Indexer?
Спасибо!
РЕДАКТИРОВАТЬ (10 октября): Марк любезно предоставил исправление в protobuf-net r447 через [ProtoContract(IgnoreListHandling = true)]
,
1 ответ
Ваш тип выглядит подозрительно, как коллекция, и protobuf-net действительно пытается справиться с этим как таковым. Одним из "исправлений" было бы добавить Add(int)
метод, поскольку это то, что он собирается использовать при десериализации. Я, однако, исследую, почему наличие / отсутствие индексатора имеет значение здесь (это не сразу очевидно для меня).
Обратите внимание, что, поскольку это выглядит как коллекция, [ProtoMember(...)]
не может быть использован здесь. Я не уверен на 100%, пока не выясню, какую роль здесь играет индексатор.
Ах ах; К; выяснил, почему индексатор подключается - по сути, после обнаружения IEnumerable
пытается идентифицировать Type
коллекции; он использует различные сигналы:
<T>
вICollection<T>
SomeType
вAdd(SomeType)
SomeType
вpublic SomeTime this[int index] {...}
индексатор
из них применяется только последний. Тем не менее, ИМО, вероятно, следует также использовать <T>
в IEnumerable<T>
(Я мог бы настроить это) - это, по крайней мере, сделало бы этот сценарий менее причудливым (как и улучшение сообщения об ошибке, которое я сделаю).
Подводя итоги, можно сказать, что protobuf-net имеет очень много специфической обработки для вещей, которые пахнут как коллекции; лично я бы бросил IEnumerable<T>
поддержка, и пусть абоненты проходят через .data
вместо; сообщение будет (в какой-то момент) отображать:
Не удалось разрешить подходящий метод Add для {FullName}