Measurity
Measurity

Reputation: 1346

How to deserialize generic dictionary with object value in protobuf-net using a proxy/shim property?

I've tried using the solutions in this post. Both the property and the surrogate didn't work. The cause would most likely be that protobuf-net doesn't work on dictionary directly but serializes the types a dictionary contains (and a surrogate on object is impossible).

My test code

class Program
{
    static void Main(string[] args)
    {
        var library = new Library();
        library.Keeper.Add("Harry Potter", "blablabla text... text...");
        library.Keeper.Add("Other book", "Awesome story.");

        // Write and read to test serializing.
        Library deserialize;
        using (var ms = new MemoryStream())
        {
            Serializer.Serialize(ms, library);

            ms.Flush();
            ms.Position = 0;

            deserialize = Serializer.Deserialize<Library>(ms);
        }

        Console.WriteLine(deserialize.Keeper.Count);
    }
}

Library class

[ProtoContract]
public class Library
{
    public Dictionary<string, object> Keeper { get; set; }

    [ProtoMember(1)]
    public Dictionary<string, string> KeeperSer
    {
        get
        {
            var res = new Dictionary<string, string>();
            foreach (var pair in Keeper)
            {
                res.Add(pair.Key, TypeDescriptor.GetConverter(pair.Value.GetType()).ConvertToInvariantString(pair.Value));
            }
            return res;
        }
        set
        {
            var set = new Dictionary<string, object>();
            foreach (var pair in value)
            {
                set.Add(pair.Key, pair.Value);
            }
            Keeper = set;
        }
    }

    public Library()
    {
        Keeper = new Dictionary<string, object>();
    }
}

I've also tried adding [ProtoIgnore] to the Keeper property. Adding a breakpoint at the setter of either KeeperSer or Keeper never triggers when running the project. The getters do work and the data is being written by protobuf-net to the MemoryStream. The length also varies when adding new items to the Library.

The reason for the Dictionary<string, object> is that I'm using TypeDescriptor.GetConverter(Type) in another project. And I want to dynamically convert types to my required type.

What am I missing to make the setter of the proxy/shim property KeeperSer working?

Upvotes: 1

Views: 859

Answers (1)

Measurity
Measurity

Reputation: 1346

Through testing it seems that any IEnumerable<object> compatible type just won't work in any way with Protobuf-net because it doesn't know how to handle it at all. The setter of those types never get called even though no error is thrown. Besides that, using a generic surrogate to 'cheat' the implicit operator gives a recursive loop inside Protobuf-net.

For now, I think I need to go with just storing a textual representation of the object data (Dictionary<string,string>) and never use Dictionary<string,object> in conjunction with the Protobuf-net serializer.

Upvotes: 1

Related Questions