I’m new to the this Protobuf.net,
we have many classes and it is inherited with parent classes, some times it is multi-level inherited.
we can’t add [ProtoInclude()] everywhere.
I don’t know we really need this or any alternative way available. (like wise versa – in Derived class we can mention the type of Base class).
We also tried directly setting this into to while serializing only
public static void RegisterTypesForObject(object obj)
{
int i = 100;
Type currentType = obj.GetType();
while (currentType != null && currentType.BaseType != typeof(object))
{
RuntimeTypeModel.Default[currentType.BaseType].AddSubType(i, currentType);
currentType = currentType.BaseType;
i++;
}
}
this methods sets it’s parent and subclasses, but it works only one time.
If we try to serialize one class and second time different class then we are getting an error
‘The type cannot be changed once a serializer has been generated for TrackingObject’.
you can refer the code for here – link.
We should keep the all values after deserializing.
1
When the deserializer encounters a base type it needs to know what concrete type to deserialize. So if I have Base
, DerivedA
& DerivedB
and serialize Base objectToSerialize = new DerivedA()
, it will use the protoInclude Id to know it should create DerivedA
and not DerivedB
.
This approach is not unique for Protobuf.net, System.text.json does something fairly similar. The old BinaryFormatterSerializer on the other hand essentially included the full type name, but this is a major security problem since you could make the deserializer create an object of an arbitrary type!
If you call your example code with both DerivedA
and DerivedB
you will correctly get an error, since you are telling the type model to use the same id for both types.
You could generate IDs dynamically if you are careful to keep track of the ids already used for each base type. But this is not something I would recommend unless you are 100% certain that an id will never ever refer to another type. I would personally be much more comfortable with a conventional, manually managed, serialization model. Or if you are committed to generated code, perhaps keep each set of generated classes as a separate, versioned, model to ensure deserialization will work.
1