I'm considering migrating current WCF-based based application to protobuf-net.Grpc. It seems to be doable, however I was not able to make protobuf-net serialize properties of (DTO classes) base class without including all derived classes with [ProtoInclude] attribute.
Simplified class hierarchy:
[DataContract]
public abstract class DtoBase
{
[DataMember(Order = 1)]
public int Id { get;set; }
[DataMember(Order = 2)]
public int Version { get;set; }
[DataMember(Order = 3)]
public EditState EditState { get;set; }
}
[DataContract]
public class PersonDto : DtoBase
{
[DataMember(Order=4)]
public string FirstName { get;set; }
[DataMember(Order=5)]
public string LastName { get;set; }
}
I have investigated related questions and it all boils down to the fact that specific type should be known during deserialization - or there should be a way to determine it. Our service methods already know the specific subclass to use, e.g. we have methods like
[ServiceContract]
public interface IPersonService
{
[OperationContract]
ScalarResult<PersonDto> GetById(personId);
}
DataContractSerializer can do that - deserialize base class properties, when specific subclass is already known. It needs hints (known types) when you deserialize subclass having base class signature, like returning PersonDto instead of DtoBase. But when specific subclass is known, known types are not needed and everything just works.
So the question is how to do the same with protobuf-net? And if it's not possible, why?
Protobuf-net, like any library, makes certain assumptions and compromises. If it wants to support additional scenarios, they need to be specified, designed, implemented, tested and supported - all of which takes time. So far, the scenario you describe: hasn't had that time invested.
It may be possible to configure the base-type properties using the RuntimeTypeModel
API, but I must emphasize: whenever a question arises that is essentially:
My existing model isn't working well with my chosen serializer
my default response (based on literally decades of experience in this field) is:
If your existing model isn't a great fit for a different serializer: stop fighting the serializer. Instead, create a new model that works perfectly with your new choice of serializer, and shim between models at the point of (de)serialization