Search code examples
c#protobuf-net

Binding a ProtoInclude to the corresponding RuntimeTypeModel binding doesn't work


I'm currently trying out protobuf-net, and have got problem with serialization of the following class structure:

[ProtoContract]
public abstract class WorkerResponseBase
{
    [ProtoMember(1)]
    public WorkerErrorMessage ErrorMessage { get; set; }

    [ProtoMember(2)]
    public bool IsSuccess { get; set; }

    [ProtoMember(3)]
    public bool IsError { get; set; }

    protected WorkerResponseBase()
    {
    }

    protected WorkerResponseBase(bool isSuccess, [CanBeNull] string errorMessage)
    {
        IsSuccess = isSuccess;
        IsError = !isSuccess;
        ErrorMessage = new WorkerErrorMessage(errorMessage);
    }
}

[ProtoContract()]
public class WorkerResponse<TPayload> : WorkerResponseBase
{
    [ProtoMember(4)]
    public TPayload PayloadOrNull { get; private set; }

    ....
}

When I first tried it with a concrete class as in e.g. WorkerResponse<LoginResult>, I was only able to have PayloadOrNull serialized.

Alright, I got to google a bit on how to make this work. I found this answer: ProtoBuf-Net ProtoInclude Generic Type Subclass

People mentioned, that [ProtoInclude] is required.

So, for testing this, I was trying to decorate the WorkerResponseBase with [ProtoInclude(100, typeof(WorkerResponse<LoginResult>))]. Bingo, serialization works perfectly.

Now, as you might be able to imagine, this is a very generic container for a response, so I wouldn't want to have to define all possible TPayloads in the base class, so a bit further down in the linked comment I found, that I should also be able to do this dynamically, and eventually via reflection.

So for testing purposes, I did the following instead of the [ProtoInclude]:

RuntimeTypeModel.Default.Add(typeof(WorkerResponseBase), false)
    .AddSubType(100, typeof(WorkerResponse<LoginResult>));

However, when I run this, no serialization works at all, not even the serialization of the PayloadOrNull.

So, what am I doing wrong here?


Solution

  • The false in your code (to Add) is basically saying "and I'm going to control everything myself, don't process the properties and their attributes - I'll tell you explicitly". Since you're not doing that, you probably want to pass true. In the pending V3 API, this is an optional parameter that defaults to true.