I try to serialize a tree which is composed out of either a Craft or a Reagent:
[ProtoContract] [ProtoInclude(1, typeof(Craft))] [ProtoInclude(2, typeof(Reagent))] public interface IReagent : IEquatable { [ProtoMember(1)] int ItemId { get; set; } [ProtoMember(2)] int Quantity { get; set; } }[ProtoContract] public class Reagent : IReagent { [ProtoMember(1)] public int ItemId { get; set; } [ProtoMember(2)] public int Quantity { get; set; } }
[ProtoContract] public class Craft : IReagent { [ProtoMember(1)] public int Skill { get; set; }
[ProtoMember(2)] public Profession Profession { get; set; } [ProtoMember(3)] public List<IReagent> Reagents { get; set; } [ProtoMember(4)] public int ItemId { get; set; } [ProtoMember(5)] public int Quantity { get; set; }}
Serialization code:
public class ProtobufMessageSerializer<T> : ISerializer<T> { private readonly ILog logger; public ProtobufMessageSerializer(ILog logger) { this.logger = logger; } public byte[] Serialize(T entity) { byte[] message = new byte[0]; try { using (var ms = new MemoryStream()) { Serializer.Serialize(ms, entity); message = ms.ToByteArray(); } logger.Info(string.Format("Serialized message with a length of: {0}", message.GetHumanReadableSize())); } catch (Exception ex) { logger.Warn(ex); } return message; } public T Deserialize(byte[] message) { T result = default(T); try { using (var ms = new MemoryStream(message)) { result = Serializer.Deserialize<T>(ms); } } catch (Exception ex) { logger.Warn(ex); } return result; } }Test code:
[Test] public void TestSerializer() { var responseSerializer = container.Resolve<ISerializer<IReagent>>(); var repos = container.Resolve<CraftRepository>(); var craft = repos.GetAll().First(); var serializedForm = responseSerializer.Serialize(craft); var deserializedForm = responseSerializer.Deserialize(serializedForm); Assert.NotNull(deserializedForm); }Upon serializing I get:
The type cannot be changed once a serializer has been generated for Bargains.Data.Craft (Bargains.Data.IReagent)Stacktrace:
at ProtoBuf.Meta.MetaType.ThrowIfFrozen() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 256 at ProtoBuf.Meta.MetaType.AddSubType(Int32 fieldNumber, Type derivedType) in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 70 at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 432 at ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(Type type, Boolean demand, Boolean addWithContractOnly, Boolean addEvenIfAutoDisabled) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 202 at ProtoBuf.Meta.RuntimeTypeModel.GetKey(Type type, Boolean demand, Boolean getBaseKey) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 369
Basically, the interface support currently only extends to members; I should make it an error to use the serialzie/deserialize in this way, or make it work! (the latter obviously preferable).
If you introduce a wrapper such as:
and serialize that, then it should work. You will also need to fix the following broken contract:
(the numbers cannot be duplicated inside a single type)