Question

Are there any known issues when using ProtoBuf.NET with a SortedDictionary? Specifically, we're using a SortedDictionary<CustomTKey, CustomTValue> (with the appropriate IComparer<CustomTKey> implementation but that's probably unrelated to ProtoBuf.NET's focus)

It's passing some basic tests at our end but wanted to know if there were any known issues or concerns to watch out for.

If it works, does the working extend in a general manner to other strongly types collection classes in the BCL (eg: Dictionary, SortedList etc)? I know for sure it works very well with Lists!

Was it helpful?

Solution

protobuf-net tries to avoid coding to any specific collection types, and instead tries to detect some key patterns; in particular, anything that looks like IList, ICollection<T>, or even just a custom iterator and Add(Foo), where the GetEnumerator() returns an iterator where the .Current is of type Foo.

SortedDictionary<TKey,TValue> implements ICollection<KeyValuePair<TKey, TValue>>, which is what protobuf-net detects and uses; so the library treats it simply as a collection of key-value-pairs, calling .Add etc. KeyValuePair<TKey,TValue> is treated again by pattern logic as an "auto tuple": it has a constructor that takes all of the public members, so it maps them up in that order (the constructor is KeyValuePair(TKey key, TValue value), so .Key is mapped as field 1, and .Value is mapped as field 2). Putting this together, protobuf-net maps:

[ProtoContract]
class Foo
{
    private readonly SortedDictionary<string, int> items =
        new SortedDictionary<string, int>(
        StringComparer.InvariantCultureIgnoreCase);
    [ProtoMember(1)]
    SortedDictionary<string, int> Items { get {  return items; } }
}

via the schema (verifiable via Serializer.GetProto<Foo>()):

message Foo {
   repeated KeyValuePair_String_Int32 Items = 1;
}
message KeyValuePair_String_Int32 {
   optional string Key = 1;
   optional int32 Value = 2;
}

So basically, it should work fine; the only thing to watch would be to ensure that any custom IComparer<CustomTKey> gets applied. I've done that above by only giving protobuf-net access to the getter, and performing the collection initiation inside our custom type - but you could also use a before-deserialization callback to do the same thing if you wanted to enable constructor-skipping.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top