5

I have read many questions about inheritance feature in protobuf-net. I just wonder that if I can use [DataContract],[DataMember] in the same way of using [ProtoContract],[ProtoMember]. Why I could not use [KnowType] instead of using [ProtoInclude]?

I raise this question because I used [DataContract],[DataMember] for protobuf-net's serialization already. There was no need to add "Protobuf-net". It used only "System.Runtime.Serialization".

But... Now if my class need to inherit from some class, do I have to add "Protobuf-net" for [ProtoInclude] attribute? for example,

using System.Runtime.Serialization;
namespace test
{

[DataContract]
/// [KnowType(typeof(SomeClass))]
/// or
/// [ProtoInclude(100,typeof(SomeClass))]
public class BaseClass
{
   //...
   [DataMember(Order=1)]
   public string BlahBlahBlah {get; set;}
}

[DataContract]
public class ChildClass1 : BaseClass
{
   //...
   [DataMember(Order=1)]
   public string BlahBlahBlah {get; set;}
}
}// end namespace

finally, I wonder if I have 100 child class, Won't I drive myself crazy adding 100 [ProtoInclude] tags inside base class?

Thx in adv for any help

vee

tong
  • 259
  • 5
  • 23

1 Answers1

5

EDIT: this is no longer required in v2 - you can specify this at runtime, or use DynamicType.


The reason for this is that the protobuf wire format (devised by Google) does not include any type metadata, and so we need some way of knowing what type of object we are talking about. [KnownType] doesn't provide this information, and there is no clear way of providing a robust key independently.

Actually, protobuf doesn't support inheritance either - protobuf-net shims around that by treating sub-types as nested messages. So a ChildClass1 actually appears in transit as though BlahBlahBlah was a property of a sub-object, a bit like:

message BaseClass {
    optional ChildClass1 ChildClass1 = 1;
    optional SomeOtherSubType SomeOtherSubType = 2;
}
message ChildClass1 {
    optional string BlahBlahBlah = 1;
}

etc

Re omitting it; in "v2", you have the option of specifying this data outside of the type model, via your own code. This means you don't need to decorate everything, but it still needs some mechanism to associate keys with types.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • less SO, more protobuf-net development! Can't wait for v2. – djdd87 Jun 23 '10 at 20:18
  • Thank you very much for your information. I still wonder If I have 27 child classes implemented only 1 base class, I have to add 27 [ProtoInclude] tags inside base class. Is it correct? – tong Jun 24 '10 at 04:13
  • @vee - in the current downloadable version, yes. In "v2", no: but *somewhere* you need to give each sub-type a number. But it doesn't have to be via attributes. – Marc Gravell Jun 24 '10 at 06:23
  • @MarcGravell: I am starting to use v2. How do I exactly specify the attributes with my own code? I dont want to use ANY decoration in existing classes. Possible? Also, can I use v2 in production? – Sam Jun 07 '12 at 10:49
  • @Sam we've been using v2 in production here at SO for... well, ages and ages. And ages. So: yes. For not using attributes, see `RuntimeTypeModel`. This has APIs for describing each type (`MetaType`) and each member (`ValueMember`). If you have a specific example, let me know and I'll show it in full. – Marc Gravell Jun 07 '12 at 12:40
  • @MarcGravell I have scenario as described above with inheritance of two classes decorated with DataContract attributes, the issue that I'm serializing the child class but the DeepClone omit the properties from the base class unless I'm adding the ProtoInclude on the parent class, is this normal? – Tamir Nov 14 '12 at 10:57
  • @Tamir unless protobuf-net has been explicitly told about the inheritance relationship, it will not consider it. So yes, it would be expected. If you don't want to add attributes, you can also configure it via `RuntimeTypeModel.Default[typeof(BaseType)].AddSubType(fieldNumber, typeof(DerivedType));` – Marc Gravell Nov 14 '12 at 11:00
  • @MarcGravell this behavior can be understood when the DeepClone gets the base class as parameter, so the model can't know all the inheritors, but when it gets the child type, it can infer the parents by inspecting the base type of the instance, this is what I thought and what seems to be intuitive. will it be in future release? [currently I'm using v2.0.0.594] – Tamir Nov 14 '12 at 11:06
  • @Tamir it isn't enough to just know "these two things are related" - it needs a robust, reliable and repeatable way to know which `fieldNumber` represents that relationship - and *that* cannot be inferred. Hence the need to specify it, either by `[ProtoInclude(...)]` or by `AddSubType(...)`. Incidentally, that is also why it can't make much use of `[KnownType]` or `[XmlInclude]`. – Marc Gravell Nov 14 '12 at 11:09
  • @MarcGravell thank you so much for your answer and all the great work! – Tamir Nov 14 '12 at 11:11