4

using protobuf-net.dll 2.0.0.431

I'm attempting to serialize a class hierarchy using [DataContract] and [DataMember].

[DataContract]
[KnownType(typeof(LoginRequest))]    
public class Message
{
    [DataMember(Order = 2)]
    public int Id { get; set; }
}

[DataContract]
public class LoginRequest : Message
{
    [DataMember(Order = 1)]
    public string Username { get; set; }

    [DataMember(Order = 2)]
    public string Password { get; set; }                
}

and to serialize/deserialize:

            using (var file = File.Create(filename))
            {
                Serializer.Serialize(file, loginRequest);
            }

            LoginRequest deserialized;
            using (var file = File.OpenRead(filename))
            {
                deserialized = Serializer.Deserialize<LoginRequest>(file);
            }

            ReflectionUtils.Compare(loginRequest, deserialized);

The Id field of abstract class Message is not serialized.

To make it work I have to decorate Message with:

[ProtoInclude(1, typeof(LoginRequest))]

Why is this? I've read this similar question but Marc concludes that 'this is no longer required in v2 - you can specify this at runtime, or use DynamicType'

I would prefer not to specify anything extra other than KnownType

Community
  • 1
  • 1
wal
  • 17,409
  • 8
  • 74
  • 109

1 Answers1

1

[KnownType(...)] is not enough, as the library also need a unique (for that type) integer to use as the key (the 1 in the example). Inferring it qutomatically is too risky, as it could cause unexpected breaks when tweaking the type (and version safety is a very deliberate design goal).

If you don't want to add an attribute for this, you can tell it what it needs at runtime, i.e. (in your startup code):

RuntimeTypeModel.Default[typeof(Message)]
    .AddSubType(1, typeof(LogonRequest));
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Its not a big issue it just doubles the height of the attribute decorations. :) Whilst on this topic, and without posting another question or any code samples (altho I might have to) - I am decorating my `IService` with `[ProtoBehaviorAttribute]` - I have found that I *must* add both `[KnownType]` AND `[ProtoInclude(x)]` to have serialization work. If I exclude ProtoInclude the client-side can receive (?) but not send a message. If I exclude [KnownType] then the server cannot send the message (but no error, the channel just faults!) Could you comment? – wal Sep 30 '11 at 00:02
  • @wal in all honesty that is new to me; I would have to investigate – Marc Gravell Sep 30 '11 at 06:45