Question

I'm trying to integrate the awesome protobuf-net into an existing codebase, but am encountering a crash when it tries to handle a custom type. A small demonstration is below: it will throw an InvalidOperationException in ProtoBuf.Serializers.ListDecorator. But if you comment out the indexer (or remove the IEnumerable implementation) then it runs cleanly.

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>(); }
}

Am I doing something wrong? How can I tell the protobuf-net Serializer to just ignore that Indexer property?

Thanks!

EDIT (Oct 10): Marc has kindly provided a fix in protobuf-net r447 via [ProtoContract(IgnoreListHandling = true)].

Était-ce utile?

La solution

Your type looks suspiciously like a collection, and protobuf-net is indeed trying to handle it as such. One "fix" would be to add an Add(int) method, as that is what it is going to want to use when deserializing. I am, however, investigating why the presence/absence of the indexer makes a difference here (that is not immediately obvious to me).

Note that because this looks so much like a collection, the [ProtoMember(...)] might not be used here. I'm not 100% certain until I find out what role the indexer is playing here.


Ahah; k; found why the indexer is getting involved - essentially, after detecting IEnumerable, it is trying to identify the Type of the collection; it uses various cues:

  • the <T> in ICollection<T>
  • the SomeType in Add(SomeType)
  • the SomeType in a public SomeTime this[int index] {...} indexer

of these, the only one that applies is the last. However, IMO it should probably also use the <T> in IEnumerable<T> (I might tweak this) - this would at least make this scenario less bizarre (as would improving the error message, which I'll do).

To summarize, protobuf-net has lots of very particular handling for things that smell like collections; personally, I'd drop the IEnumerable<T> support, and let callers go via .data instead; the message will (at some point) display:

Unable to resolve a suitable Add method for {FullName}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top