I’m having issues deserializing a Guid when the Guid is defined in a message base class. When I have the following message.
[DataContract]
public abstract class GatewayPageEvent:IDomainEvent
{
protected GatewayPageEvent()
{
On = DateTime.Now;
}
[DataMember(Order = 1)] public Guid GatewayPageId { get; set; }
[DataMember(Order = 2)] public DateTime On { get; set; }
}
[DataContract]
public class GatewayPageAddedToSite : GatewayPageEvent
{
[DataMember(Order = 3)]public string Url { get; set; }
[DataMember(Order = 4)]public string SiteCode { get; set; }
}
GatewayPageId is always deserializing as Guid.Empty. Here’s a unit test I wrote that fails. I’m kinda stumped…
public string Serialize(object t)
{
var memoryStream = new MemoryStream();
ProtoBuf.Serializer.Serialize(memoryStream, t);
return Convert.ToBase64String(memoryStream.ToArray());
}
public object Deserialize(string value, Type targetType)
{
var bytes = Convert.FromBase64String(value);
var stream = new MemoryStream(bytes);
return ProtoBuf.Serializer.NonGeneric.Deserialize(targetType, stream);
}
[Test]
public void protobuf_serialization_can_deserialized_guids()
{
var originalMessage = new GatewayPageAddedToSite
{GatewayPageId = Guid.NewGuid(), SiteCode = "dls", Url = "test"};
var serializedMessage = Serialize(originalMessage);
var @event = (GatewayPageAddedToSite)Deserialize(serializedMessage, typeof(GatewayPageAddedToSite));
Assert.AreEqual(@event.GatewayPageId, originalMessage.GatewayPageId);
}
I know Guids work fine because the following unit test works just fine.
[Test]
public void guids_work_fine()
{
var original = Guid.NewGuid();
var serialized = Serialize(original);
var deserialized = (Guid) Deserialize(serialized, typeof (Guid));
Assert.AreEqual(original,deserialized);
}
Am I defining my contract wrong? Or is this a problem with protobuf-net?
With protobuf-net, it needs to know about inheritance ahead of time (actually, so does
DataContractSerializer, usually – via[KnownType(...)]). In the case of protobuf-net, it also needs a unique key to distinguish them, something like:(i.e. the base-type needs to be told about the derived types)
Note that the numbers only need to be unique within each type, so there is no collision between the “3” in the include vs the “3” in
GatewayPageAddedToSite– and actually,GatewayPageAddedToSitecould use “1” and “2” if it wants.If your domain model is generated, then a separate partial class file might help:
If you really don’t want to upset your model with these things, then in v2 you can do this at runtime instead:
any of that make it work?