Protobuf-net Serialization as a base class

I would like to use protobuf-net to serialize a derived class as a base class. In other words, I want the serialization process to discard any indications that the type is received:

[ProtoContract] class Base { [ProtoMember(1)] public string PublicInfo { get; set; } } class Derived : Base { public string SecretInfo { get; set; } } class Program { static void Main(string[] args) { Derived d = new Derived() { PublicInfo = "public info", SecretInfo = "secret info" }; using (var ms = new MemoryStream()) { Serializer.NonGeneric.Serialize(ms, d as Base); ms.Seek(0, SeekOrigin.Begin); Base deserialized = Serializer.Deserialize<Base>(ms); Console.WriteLine("Deserialized type: " + deserialized.GetType()); Console.WriteLine("Deserialized value: " + deserialized.PublicInfo); } Console.ReadLine(); } } 

I want the above program to create

  Deserialized type: Base Deserialized value: public info 

but instead, I get an exception from "Type not expected."

If I add [ProtoContract] to Derived , the PublicInfo field PublicInfo not be set. And if I also add [ProtoInclude(2, typeof(Derived))] to Base , then the deserialized type is Derived , not Base , as I want.

What am I missing? Sorry if I missed the answer elsewhere. I think I'm asking for something like the opposite of this question , although I would not want to explicitly add fields through RuntimeTypeModel .

+4
source share
2 answers

If your hierarchy is not too complex, you might consider creating a derived type using a serialization member instead of inheriting from it.

 [ProtoContract] class Generic { [ProtoMember(1)] public string PublicInfo { get; set; } } class Specialized { public Generic Generic { get; set; } public string SecretInfo { get; set; } } 

There are some parts of your object that can be serialized, and some parts are not compatible with serialization. Do not mix them in one inheritance hierarchy. Because this does not correspond to the concept of specialization of the TOE. The base class is serializable, the derived class does not exist, however, for inheritance, the derived class must support everything that the base class already supports.

+4
source

Most serializers will strangle this, as they are meant to be able to reproduce what you started with. The answer suggested in the corresponding question will be sufficient, but it is a bit hacked and, as such, requires a bit of voodoo with RuntimeTypeModel . In this regard, I really like the solution in DonAndre's answer, which keeps everything pretty clean (and Specialized may even be omitted from the contract with Generic and SecretInfo included).

The only thing to do is to convince him that your Derived is actually a proxy. The proxy detection code is not currently configured at runtime, however it would not be easy to trick it (abuse of some implementation knowledge), i.e.

 namespace NHibernate.Proxy { internal interface INHibernateProxy {} // pretty spectacularly evil } ... class Derived : Base, INHibernateProxy {} 

Now that he discovers that he does not recognize Derived , he should check the general proxy patterns, find that he is very similar to the NHibernate proxy, and use the base type. Really awful and rough.

+3
source

All Articles