12

How to I serialize an object like this with protobuf-net:

public class MyObject{
   public string Key {get; set;}
   public List<Object> Values {get; set;}
}

When I try to serialize this with a TypeModel protobuf-net throws an error stating that it doesn't know how to serialize System.Object. Now I know that Values will only ever contain primitives (int, string, float, DateTime, etc.). So how do I let protobuf-net know about this?

Timothy Baldridge
  • 10,455
  • 1
  • 44
  • 80
  • It is, however, serializable. – cHao Sep 21 '11 at 22:37
  • I don't know protobuf but you're asking an awful lot from a serializer. – H H Sep 21 '11 at 22:37
  • .NET DataContract serializes it just fine.... And yes, DateTime has a sort-of weird semi-primitive status in .NET. For instance, int? is valid and MyObject? is not, because MyObject is not a primitive, however DateTime? is perfectly valid. So no, perhaps not a primitive, but it's a value type, and it's built-in, and serializable. – Timothy Baldridge Sep 21 '11 at 22:42
  • Note that all `struct`s are a `ValueType` and since `int` is just `struct System.Int32`.... Consider the code `(42).GetType().BaseType` and `var v = new List() { 1, Guid.NewGuid() }`. However, this likely doesn't help with the problem at hand at all (it constrains the type to a `struct`, but not to a "supported serializable type") even though I find it interesting :) The "issue" is that protobuf-net only knows how to serialize/encode a very limited subset of types (whereas DCS and XmlSerializer are much more robust). –  Sep 21 '11 at 22:47
  • 2
    I think it may actually be a more fundamental issue: unless I am mistaken, protocol buffers only support homogenous lists..? –  Sep 21 '11 at 22:57

2 Answers2

9

This isn't really doable in pure ProtoBuf, in any sense. ProtoBuf is strongly typed, yet does not contain type information in the message; type information is always specified externally. Thus there are two "good" solutions; Ie, solutions which would be easy to interpret by a protobuf implementation other than Protobuf-net (Which you may or may not care about, but marc sure seems to).

1: Replace List<object> with List<PrimitiveType> where PrimitiveType contains optional fields corresponding to all the 12-or-so primitive types (Depending on your definition of "Primitive Type".), and you ensure only one of those is filled in on each instance.

2: Replace List<object> with a combination of List<int>, List<double>, List<string> etc.

DanielOfTaebl
  • 713
  • 5
  • 13
0

See In Protobuf-net how can I pass an array of type object with objects of different types inside, knowing the set of potential types in advance.

As per Marc post (the author of Protobuf.NET) object is problematic. Although I can't find it right now, I distinctly remember seeing a check for object in the source to throw an exception against attempts to serialise object properties directly.

To work around this you should use a more specific class to be serialised and not use object directly. You can use IProtoSerializer to implement custom serialisation/deserialisation. Protobuf will also support ISerializable and IXmlSerializable interfaces if that helps.

Community
  • 1
  • 1
Bernie White
  • 4,780
  • 4
  • 23
  • 21
  • 2
    To clarify: protobuf-net not not *consume* `ISerializable` nor `IXmlSerializable` - rather it can be used to *implement* them. `IProtoSerializer` is an *internal* class, and cannot be used in isolation. – Marc Gravell Sep 24 '11 at 07:33