2011-10-07 114 views
1

我有问题反序列化guid时定义的消息基类。当我收到以下消息时。protobuf网Guid反序列化Guid.Empty当使用继承

[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的问题吗?

回答

0

随着protobuf网,它需要提前知道继承(实际上,DataContractSerializer,通常也是如此 - 通过[KnownType(...)])。在protobuf网的情况下,它也需要一个唯一的密钥来区分他们,是这样的:

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

任何使它工作?

+0

尝试一下,但如果是这样的话,不会是 Assert.AreEqual(originalMessage.On.Date,@ event.On.Date); 会失败,但事实并非如此。 –

+0

@Elliott 2秒,而我启动了一个测试平台... –

+0

@Elliot似乎为我解决了......? –