protobuf-net Как избежать сбоев при работе с индексированными свойствами - PullRequest
4 голосов
/ 05 октября 2011

Я пытаюсь интегрировать удивительный protobuf-net в существующую кодовую базу, но я сталкиваюсь с падением, когда он пытается обработать пользовательский тип.Ниже приведена небольшая демонстрация: она выдаст 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 Ответ

4 голосов
/ 05 октября 2011

Ваш тип выглядит подозрительно, как коллекция, и protobuf-net действительно пытается справиться с этим как таковым. Одним из "исправлений" было бы добавление метода Add(int), поскольку , который - это то, что он собирается использовать при десериализации. Я, однако, исследую, почему наличие / отсутствие индексатора имеет значение здесь (это не сразу очевидно для меня).

Обратите внимание, что , поскольку выглядит очень похоже на коллекцию, [ProtoMember(...)] здесь может не использоваться. Я не уверен на 100%, пока не выясню, какую роль здесь играет индексатор.


Ахаха; К; обнаружил, почему индексатор подключается - по сути, после обнаружения IEnumerable он пытается идентифицировать Type коллекции; он использует различные сигналы:

  • <T> в ICollection<T>
  • SomeType в Add(SomeType)
  • SomeType в public SomeTime this[int index] {...} индексаторе

из них применяется только последний. Тем не менее, IMO, вероятно, следует также использовать <T> в IEnumerable<T> (я мог бы настроить это) - это, по крайней мере, сделало бы этот сценарий менее странным (как и улучшение сообщения об ошибке, которое я сделаю).

Подводя итог, у protobuf-net очень много особой обработки для вещей, которые пахнут как коллекции; лично я бы отказался от поддержки IEnumerable<T> и позволил бы вызывающим абонентам проходить через .data; сообщение (в какой-то момент) будет отображаться:

Невозможно найти подходящий метод Add для {FullName}

...