I'm having some issues trying to serialize/deserialize a complex object graph using protobuf-net.

I'm working on a legacy application and we're using .Net Remoting to connect a GUI client to a C# service. We are seeing poor performance with overseas users due to the serialized size of our object graphs using the default BinaryFormatter, which is exacerbated by the limited bandwidth in-between the client and server (1Mbit/s).

As a quick win, I thought I'd put together a proof of concept to see if there were any performance gains to be had by using protobuf-net instead, by implementing ISerializable. As I was testing I ran into an issue whereby object references weren't being maintained.

I've put together an example which repros the issue. I'm expecting that the object in the Dictionary (Items[1]) and the object B.A will be the same as I've specified AsReference=true in the ProtoMember attribute.

It looks like someone else had a similar issue: stackoverflow.com/questions/6923891/…Standard lists and dictionaries work fine; however, I have an outstanding change request to support AsReference inside a dictionary. Meaning, Dictionary<string, Foo> won't currently run the graph code for Foo, but I can probably find a few moments to look at this if it is causing you significant pain It would be very helpful to me if the graph code did run for Foo :)
–
Lee FJan 21 '13 at 15:48

Just as an update: I've had a stab at getting it working in a way that requires no fussing. I have one remaining glitch to iron out, where-by currently the behaviour depends on the order in which types are discovered (which is clearly very undesirable), which I need to iron out.
–
Marc Gravell♦Jan 22 '13 at 22:09

Good stuff, it's nice to hear that you've been able to get something working so quickly.
–
Lee FJan 23 '13 at 9:11

The AsReferenceDefault optional attribute property on ProtoContract will be fully working from the next build
–
Marc Gravell♦Apr 12 '13 at 19:18

2 Answers
2

Edit: this should work from the next build onwards simply by marking the type's AsReferenceDefault:

[ProtoContract(AsReferenceDefault=true)]
public class A
{
// ...
}

At the current time this is sort of an unsupported scenario - at least, via the attributes it is unsupported; basically, the AsReference=truecurrently is referring to the KeyValuePair<int,A>, which doesn't really make sense since KeyValuePair<int,A> is a value-type (so this can never be treated as a reference; I've added a better message for that in my local copy).

Because KeyValuePair<int,A> acts (by default) as a tuple, there is currently nowhere to support the AsReference information, but that is a scenario I would like to support better, and I will be investigating this.

There was also a bug that meant that AsReference on tuples (even reference-type tuples) was getting out-of-order, but I've fixed that locally; this was where the "changed" message came from.

In theory, the work for me to do this isn't huge; the fundamentals already work, and oddly enough it came up separately on twitter last night too - I guess "dictionary pointing to an object" is a very common scenario. At a guess, I imagince I'll add some atribute to help describe this situation, but you can actually hack around it at the moment using a couple of different routes:

I don't like this much, because it exploits implementation details of KeyValuePair<,> (the private fields), and may not work between .NET versions. I would prefer to replaceKeyValuePair<,> on the fly via a surrogate:

Thanks for that Marc, a very helpful and comprehensive answer. I've gone with the surrogate approach and it's working well, however as you say, I imagine this scenario is relatively common so it would be nice to see it supported out of the box without having to configure surrogates for each KVP.
–
Lee FJan 22 '13 at 10:31

@Lee indeed; another reason to do that is that "precompile" currently only works with attribute-based models: it doesn't execute any code in the inspected assembly. That restricts usage on "light" frameworks (WP7/WP8/iOS/etc).
–
Marc Gravell♦Jan 22 '13 at 10:55