3

Is it possible to serialize interface-typed structs in protobuf-net, or does this only work for interface-typed classes?

I have a number of structs which I'd like to serialize, all of which implement an interface. I'm currently wrapping these in another struct (together with some meta data) in order to perform the serialization:

[ProtoContract]
public interface IData {}

[ProtoContract]
public struct MyData1 : IData { }
[ProtoContract]
public struct MyData2 : IData { }

[ProtoContract]
public struct SerializationStruct {
    [ProtoMember(1)]
    public int SomeMetadata;
    [ProtoMember(2)]
    public IData Content
}

From reading other answers (e.g. protobuf-net inheritance), I should be able to add the types to the RuntimeTypeModel using AddSubType and then serialize an instance of SerializationStruct.

This works if I use classes for MyData1 and MyData2 but if I use structs (as above) I get the error:

System.ArgumentException: MyData1 is not a valid sub-type of IData. Parameter name: derivedType

when I attempt to add it to the model, like so:

RuntimeTypeModel.Default[typeof(IData)].AddSubType(1, typeof(MyData1));
user73445
  • 141
  • 4
  • 1
    Where are you getting this exception? Can you create a [mre]? It sounds like you either did not correctly implement `IData` on `MyData1`, or you are referring to a different interface altogether where you get the exception. – Connor Low Mar 15 '21 at 15:43
  • @ConnorLow Thanks; the code posted should be sufficient to cause the problem, but I've added the specific line that causes the error to the question – user73445 Mar 15 '21 at 15:55

1 Answers1

1

I "solved" this by switching to a different library to serialize (MessagePack), which was able to handle this case using Unions. Coming back to protobuf-net, it seems that it also supports discriminated unions, although I can't find any documentation of how, and I have not got any further.

I also looked at the code in protobuf-net that causes the specific error, and it appears (I think) to explicitly reject using structs as subtypes:

    private bool IsValidSubType(Type subType)
    {
        return subType is object && !subType.IsValueType
            && Type.IsAssignableFrom(subType);
    }

So I suppose the direct answer to my question is "no", but the practical answer is "there's probably a proper way to do it"

user73445
  • 141
  • 4