2011-10-07 113 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似乎爲我解決了......? –