views:

67

answers:

1

This question directly in large part to the protobuf-net maintainer(s) but anyone else please comment.

I was trying to serialize a class that contains a property which has an interface type, ie:

[DataContract]    
public class SampleDataClass
{
    [DataMember(Order=1)]
    public int Field1 { get; set; }                

    [DataMember(Order = 2)]        
    public IPayload Payload { get; set; }
}

[ProtoContract]
[ProtoInclude(1, typeof(Payload))]
public interface IPayload
{
    int Field4 { get; set; }
}

[DataContract]
public class Payload : IPayload
{
    [DataMember(Order = 1)]
    public int Field4 { get; set; }
}

I have managed to get this to work by changing the source of v1 of protobuf-net. I did not see any problem with this approach as long as ProtoInclude is defined for the interface.

Clearly to get this to compile I had to allow ProtoContract and ProtoInclude to be decorated on interfaces, plus a few other changes here and there. (note, I would have used DataContract/KnownType however these attributes are also not able to be decorated on interfaces)

Can you please comment on possible shortcomings?

+1  A: 

The main glitch I can see is that in terms of payload this moves the data into a sub-message. I have some similar designs around v2 that hopefully get around this, keeping most values in the primary message. For sanity reasons, I mainly had just v2 in mind for this change (since the two implementations would be separate, and v2 has a much better type model).

However, it should be possible to support both modes of use. If you want to send it as a patch for v1 (with the same license etc) I'd happily take a look :)

Marc Gravell
Can you elaborate further on what you mean by 'this moves the data into a sub-message'.Is there an issue (performance or other) with an interface nested far down in the object hierarchy?
wal
@wal - simply, presumably you have (using no particular notation, and changing `Field4`'s tag to 5 for clarity) `{1={len:5=value}}`. I *think* we should aim to support (but not mandate) that the serialization can be on the *interface*, so we have `{1={0},5=value}`, where we still *have* the concrete sub-type, but **unless** it exposes some specific additional data, we serialize at the interface level.
Marc Gravell