Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol Buffers In C#: How Are Boxed Value Types Handled

In the following examples:

public class RowData
{
    public object[] Values;
}

public class FieldData
{
    public object Value;
}

I am curious as how either protobuf-net or dotnet-protobufs would handle such classes. I am more familiar with protobuf-net, so what I actually have is:

[ProtoContract]
public class RowData
{
    [ProtoMember(1)]
    public object[] Values;
}
[ProtoContract]
public class FieldData
{
    [ProtoMember(1)]
    public object Value;
}

However I get an error saying "No suitable Default Object encoding found". Is there an easy way to treat these classes, that I am just not aware of?

To elaborate more on the use case:

This is a scaled down version of a data class used in remoting. So essentially it looks like this:

FieldData data = new FieldData();
data.Value = 8;

remoteObject.DoSomething(data);

Note: I've omitted the ISerializable implementation for simplicity, but it is as you'd expect.

like image 261
Greg Dean Avatar asked Jan 23 '23 20:01

Greg Dean


1 Answers

Re protobuf-net, which I maintain:

The issue here isn't value-types (which it will often handle fine) - it is the open object usage, which means it simply doesn't know what data to expect, and thus how to encode/decode it.

At the moment, I can't think of an easy/clean way to handle that. It will handle a range of common value-type scenarios, lists, and any level of hierarchy based on contracts (data-contract, proto-contracts, or some xml-schemas), but it needs a clue.

Perhaps if you can clarify the use-case, I might be able to help more? For example, the above wouldn't work very with DataContractSerializer or XmlSerializer either...

Re dotnet-protobufs; I can't really comment, but I'm pretty sure it would be even less forgiving; it is intended to be used with classes generated from a .proto file, so object would simply never enter into the model (Jon: correct me if I am wrong).

If you do leave more info, could you kindly post a comment here? So I can find it easily... Alternatively, drop me a mail directly (see my SO profile).


edit - here's the hacky thing I had in mind - it isn't working at the moment, but I'll figure out why tomorrow (probably). Note that in theory the extra members could all be private - I'm just trying to make it easy while debugging. Note that this doesn't take any extra storage. Like I say, it doesn't work today, but it should - I'll find out why...

[ProtoContract]
public class FieldData
{
    public object Value {get;set;}

    [ProtoMember(1)]
    public int ValueInt32 {
        get { return (int)Value; } set { Value = value; } }
    public bool ValueInt32Specified {
        get { return Value != null && Value is int; } set { } }

    [ProtoMember(2)]
    public float ValueSingle {
        get { return (float)Value; } set { Value = value; } }
    public bool ValueSingleSpecified {
        get { return Value != null && Value is float; } set { } }

    // etc for expected types
}
like image 173
Marc Gravell Avatar answered Jan 31 '23 18:01

Marc Gravell