2011-06-27 46 views
2

我想創建一個簡單的內存中網格,可以使用協議緩衝區序列化。protobuf-net:無法序列化類型數據,如何用協議緩衝區定義類型數據?

這個想法是用戶可以創建/定義任何類型的列(原語或用戶定義,只要他們是協議緩衝區標記)。

我的問題是你不能序列化類型數據與協議緩衝區,所以我怎麼能做到這一點?

代碼如下顯示我希望如何編碼網格的列。

非常感謝。

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     Column colOrderId = new Column("OrderId", typeof(uint)); 
     Column colOrderDesc = new Column("OrderDesc", typeof(string)); 
     Column colPrice = new Column("Price", typeof(Price)); 
     Column colOrderDateTime = new Column("OrderDateTime", typeof(DateTime)); 

     var s = colOrderId.ToBArray(); 
    } 
} 

[ProtoContract, Serializable] 
public sealed class Column 
{ 
    public Column(string name, Type type) 
    { 
     Name = name; 
     Type = type; 
    } 

    [ProtoMember(1)] 
    public string Name { get; private set; } 

    [ProtoMember(2)] 
    public Type Type { get; private set; } 
} 

[ProtoContract, Serializable] 
public sealed class Price 
{ 
    public Price(double value, string currency) 
    { 
     Value = value; 
     Currency = currency; 
    } 

    [ProtoMember(1)] 
    public double Value { get; private set; } 

    [ProtoMember(2)] 
    public string Currency { get; private set; } 
} 

public static class ProtoBufEx 
{ 
    public static byte[] ToBArray<T>(this T o) 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      ProtoBuf.Serializer.Serialize(ms, o); 
      return ms.ToArray(); 
     } 
    } 
} 
+0

我想在protobuf v2中,您可以爲類型添加一個用戶定義的序列化程序,該程序序列化爲該類型的名稱。 – CodesInChaos

+0

另一個潛在的問題是你的類型是不可變的。我不確定protobuf是否支持開箱即用,或者如果您需要另一個自定義序列化程序。 – CodesInChaos

+0

@CodeInChaos只是爲了完整性,私人設置是好的。在v1中,它也需要一個無參數的構造函數(再一次,private很好);在v2中它可以選擇性地跳過構造函數,WCF風格。 –

回答

1

這種方法存在一些問題;是的,在標準協議緩衝區中,任何種類的Type元數據都是有點調皮的,因爲它不是真正的互操作性,但是我可以在v2 的基礎上選擇啓用 - 允許您發送object等只要在內部它仍然知道你的意思。但是,對於逐個單元格的工作,即使是內置的優化(例如,它只發送相同類型的元素一次),這也將變得很昂貴。

但是IMO更好的選擇是將自己限制在一個已知類型的列表中,這些類型都是事先知道的。如果你可以做有一些有趣的技巧與繼承是非常有效的,合理適合這種情況。但實際上你會碰到這樣的:

[ProtoContract] 
[ProtoInclude(4, typeof(Column<int>))] // etc 
abstract class Column { 
    [ProtoMember(1)] 
    public string Name {get;private set;} 

    public abstract object Value {get;private set;} 
} 
[ProtoContract] 
class Column<T> : Column { 
    [ProtoMember(1)] 
    public T TypedValue { get;private set;} 
    override Value {...shim to TypedValue...} 
} 
// etc 

(僞代碼,不完整)

我會高興地引導您完成了很多的,但是你可能也想看看this blog entry看如果使用DataTable(就像我不喜歡數據訪問一樣)可能會在這裏節省一些工作量。

+0

Marc Gravell:我的目標是跨平臺工作。所以我想用對象出來?此外,網格是一個簡單的光結構,只有列和行不是一個巨大的.Net DataTable。這基本上是我用戶定義的數據存儲。謝謝 – DaveHeller

+0

@Dave沒有辦法將這種數據結構映射到易於互操作的protobuf(.proto)版本,因爲* core * protobuf規範非常少。你可以得到最接近的可選字段,但是在大多數版本中這會很糟糕 –

相關問題