2014-12-03 52 views
1

爲什麼反序列化不提供輸出類型?protobuf-net反序列化不提供輸出類型

通常,如果兩個端點正在通信,則兩端共享相同的類型。在我的情況下,我在客戶端和服務器應用程序上使用完全相同的庫。在啓動時註冊我的所有類型都在客戶端和服務器這樣的:

var metaType = RuntimeTypeModel.Default.Add(type, false); 
foreach(var prop in type.GetProperties()) 
    metaType.Add(i++, prop.Name); 

,所以我期待的Protobuf去理解它應該反序列化爲無需提供一個類型。 目前我使用這個反序列化:

RuntimeTypeModel.Default.DeserializeWithLengthPrefix(
    stream, null, type, ProtoBuf.PrefixStyle.Fixed32, 0); 

這種行爲(在其他串行太找到)迫使我有包裝的每一個對象,我想序列化和內,我有一個實際超有效載荷和其他一些幫助我理解如何反序列化有效載荷的信息。所以我可以這樣寫:

public class MySuperType 
{ 
    public byte[] Payload {get; set;} 
    public Type PayloadType {get; set;} 
} 

public object Deserialize(byte[] bytes) 
{ 
    using(var stream = new MemoryStream(bytes)) 
    { 
     var wrapperObject = Serializer.DeserializeWithLengthPrefix<MySupertype> 
      (stream, ProtoBuf.PrefixStyle.Fixed32); 

     using(var stream = new MemoryStream(wrapperObject.Payload)) 
     { 
      var actualPayloadObject = RuntimeTypeModel.Default.DeserializeWithLengthPrefix(
       stream, null, wrapperObject.PayloadType, ProtoBuf.PrefixStyle.Fixed32, 0); 

      return actualPayloadObject; 
     } 
    }  
} 

所以我基本上知道我收到的每個對象都是MySupertype類型。 我是否把事情搞亂了?

回答

1

protobuf流指示根數據類型是不正常的。它是預計調用代碼知道數據的樣子。但是,還有其他方法可以解決這個問題。例如,一種常用的方法是爲每種類型指定一個標籤編號,並使用稍微更復雜的序列化/反序列化重載執行此查找 - 但是,這仍然需要代碼來配置數字/類型之間的映射。

一個有時是更方便的方法是經常使用繼承:

[ProtoContract] 
[ProtoInclude(1, typeof(FooRequest))] 
[ProtoInclude(2, typeof(BarRequest))] 
public class RequestBase {} 

public class FooRequest : RequestBase {...} 
public class BarRequest : RequestBase {...} 

這也避免了需要Type被序列化,這是IMO不是一個好主意,當版本可能會導致問題。通過上述,您可以在整個過程中使用RequestBase - 可能使用多態性(virtualabstract方法)來獲得有趣的代碼。

+0

我用後一種方法取得了巨大的成功。 – Rotem 2014-12-03 11:33:40