protobuf-net Guid在使用继承时反序列化为Guid.Empty

时间:2011-10-07 11:41:23

标签: protobuf-net

当在消息基类中定义Guid时,我遇到了反序列化Guid的问题。当我收到以下消息时。

 [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始终反序列化为Guid.Empty。这是我编写的单元测试失败的。我有点难过......

    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);
    }

我知道Guids工作正常,因为以下单元测试工作正常。

[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);
    }

我定义合同错了吗?或者这是protobuf-net的问题吗?

1 个答案:

答案 0 :(得分:0)

使用protobuf-net,它需要提前了解继承(实际上DataContractSerializer通常也是如此 - 通过[KnownType(...)])。在protobuf-net的情况下,它还需要一个唯一的键来区分它们,例如:

[DataContract, ProtoInclude(3, typeof(GatewayPageAddedToSite))]
public abstract class GatewayPageEvent:IDomainEvent
{...}
[DataContract]
public class GatewayPageAddedToSite : GatewayPageEvent
{...}

(即需要告知基类型派生类型)

请注意,每个类型中的数字只需要唯一,因此包含中的“3”与GatewayPageAddedToSite中的“3”之间不会发生冲突 - 实际上,如果需要,GatewayPageAddedToSite可以使用“1”和“2”。

如果您的域模型已生成,则单独的部分类文件可能有所帮助:

[ProtoInclude(3, typeof(GatewayPageAddedToSite)]
partial class GatewayPageEvent {}

如果你真的不想用这些东西打乱你的模型,那么在v2中你可以在运行时这样做:

RuntimeTypeModel.Default[typeof(GatewayPageEvent)]
      .AddSubType(3, typeof(GatewayPageAddedToSite));

任何一个使它有用吗?