In protobuf, each member of a type needs an identifying number, because protobuf is number-based (it doesn't send names). As such, the trick is simply: tell it what numbers to use. For example:
class Customer {
public int Id {get;set;}
public string Name {get;set;}
}
The simplest way to specify a contract for this would be:
RuntimeTypeModel.Default.Add(typeof(Customer), false).Add("Id", "Name");
which would associate Id
with 1 and Name
with 2. When using attributes, there is some inbuilt "figure it out yourself" code, which I should really expose on the non-attribute API - things like:
- serialize all public fields + properties, in alphabetical order
- serialize all fields (public or non-public), in alphabetical order
However: both of these are pretty simple to do with reflection. Note that in either event, using reflection is a good way to run into problems if the types might change at some point.
Additional features that may help, and which I can provide more information on:
- a type factory can be specified (globally or per-instance), which can be useful for pre-populating values or using a pool of available objects
- surrogate types can be written for complex scenarios - this is useful when most of the model works fine, but one type is just too esoteric to be a good fit for serialization - but an alternative layout can be devised for which you can write conversion code in both directions
- many things that looks like a "tuple" will be handles by default - in particular, if it is publicly immutable, and has a constructor that accepts parameters that match all the public members - it will assume to serialize the members in the order specified by the constructor