简体   繁体   中英

Serializing arrays of objects with protobuf-net for C++ consumption

I've build some classes as per instructed in the following answer here in order to be able to serialize a list of generic objects; such as instances of KeyValuePair and KeyValuePair.

Unfortunately, it appears that the .proto file generated by the GetProto() method does not generate a file that can be parsed properly for C++. Subtype messages generated for arrays are suffixed with "[]". The protoc.exe chokes on the "[]" when compiling for C++.

Since the message names seem to be arbitrary for protobuf (that is, they're not actually included in the data stream), is possible to tell protobuf-net to use "_Array" instead of "[]" when naming the sub-types? Or is there some other avenue I should take so that the .proto file generated can be consumed by a C++ application?

Thanks,

Below is the relevant code and generated proto file.

The base class is:

[DataContract]
[ProtoInclude(101, typeof(KeyValuePairResponse<string>))]
[ProtoInclude(102, typeof(KeyValuePairResponse<int>))]
[ProtoInclude(103, typeof(KeyValuePairResponse<double>))]
[ProtoInclude(111, typeof(KeyValuePairResponse<string[]>))]
[ProtoInclude(112, typeof(KeyValuePairResponse<int[]>))]
[ProtoInclude(113, typeof(KeyValuePairResponse<double[]>))]
public abstract class KeyValuePairResponse
{
    protected KeyValuePairResponse() { }

    [DataMember(Order = 1, IsRequired = true)]
    public string Key { get; set; }

    public object Value
    {
        get
        {
            return this.ValueImplementation;
        }

        set
        {
            this.ValueImplementation = value;
        }
    }

    protected abstract object ValueImplementation { get; set; }

    public static KeyValuePairResponse<T> Create<T>(string key, T value)
    {
        return new KeyValuePairResponse<T>(key, value);
    }
}

and the generic class is:

[DataContract]
public sealed class KeyValuePairResponse<T> : KeyValuePairResponse
{
    public KeyValuePairResponse()
    {
    }

    public KeyValuePairResponse(string key, T value)
    {
        this.Key = key;
        this.Value = value;
    }

    [DataMember(Order = 2, IsRequired = true)]
    public new T Value { get; set; }

    protected override object ValueImplementation
    {
        get
        {
            return this.Value;
        }

        set
        {
            this.Value = (T)value;
        }
    }
}

The .proto file that GetProto<KeyValuePairResponse>() creates looks like:

message KeyValuePairResponse {
   required string Key = 1;
   // the following represent sub-types; at most 1 should have a value
   optional KeyValuePairResponse_String KeyValuePairResponse_String = 101;
   optional KeyValuePairResponse_Int32 KeyValuePairResponse_Int32 = 102;
   optional KeyValuePairResponse_Double KeyValuePairResponse_Double = 103;
   optional KeyValuePairResponse_String[] KeyValuePairResponse_String[] = 111;
   optional KeyValuePairResponse_Int32[] KeyValuePairResponse_Int32[] = 112;
   optional KeyValuePairResponse_Double[] KeyValuePairResponse_Double[] = 113;
}
message KeyValuePairResponse_Double {
   required double Value = 2 [default = 0];
}
message KeyValuePairResponse_Double[] {
   repeated double Value = 2;
}
message KeyValuePairResponse_Int32 {
   required int32 Value = 2 [default = 0];
}
message KeyValuePairResponse_Int32[] {
   repeated int32 Value = 2;
}
message KeyValuePairResponse_String {
   required string Value = 2;
}
message KeyValuePairResponse_String[] {
   repeated string Value = 2;
}

This is simply a bug in GetProto. I suggest logging it on the github protobuf-net list, or even submitting a pull request if you're feeling adventurous.

For now: Ctrl + h (find and replace) is probably your friend.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM