Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protobuf-net : Nested IEnumerable objects

I am using Protobuf-net to serialize a custom nested list. I understand that native lists cannot be nested directly, which is why I have used a container object for the inner list. However, I would also like to make my container objects IEnumerable but this means Protobuf-net throws it out with the error:

Nested or jagged lists and arrays are not supported

Here is an example of my list structure which causes the error:

[ProtoContract]
public class MyOuterList<T>
{
    [ProtoMember(1)]
    readonly List<MyInnerList<T>> nestedData = new List<ObjectList<T>>();
}

[ProtoContract]
public class MyInnerList<T> : IEnumerable<T>
{
    [ProtoMember(1)]
    private readonly List<T> data = new List<T>();
}

The fix is to remove IEnumerable from MyInnerList but obviously that prevents it being directly iterable. Is there a sneaky attribute like [ProtobufCustomObjectSoPleaseIgnoreIEnumerable] that could be used?

The best alternative I have come up with so far is to use an Enumerable property as shown below but I fear that the property could still be cast back to a list again. I would prefer to be using GetEnumerator/yield in some way but I can't see how.

[ProtoContract]
public class MyInnerList<T>
{
    [ProtoMember(1)]
    private readonly List<T> data = new List<T>();

    public IEnumerable<T> Data
    {
        get { return this.data; }
    }
}
like image 942
Tom Makin Avatar asked May 09 '13 10:05

Tom Makin


1 Answers

Is there a sneaky attribute like [ProtobufCustomObjectSoPleaseIgnoreIEnumerable] that could be used?

yup:

[ProtoContract(IgnoreListHandling=true)]
public class MyInnerList<T> : IEnumerable<T>
{
    [ProtoMember(1)]
    private readonly List<T> data = new List<T>();
}

sneaky is sneaky. IgnoreListHandling has the intellisense documentation:

If specified, do NOT treat this type as a list, even if it looks like one.

Also, due to multiple requests like this one, I plan on looking at implementing support for jagged arrays / lists shortly. The plan is to basically get the runtime to spoof the wrapper with a member (field 1) in the serializer's imagination, so you can use List<List<T>> and it'll work just like your model above (it will even be wire-compatible, since you sensibly chose field 1).

like image 115
Marc Gravell Avatar answered Oct 14 '22 09:10

Marc Gravell