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?
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
.