2012-04-13 165 views
1

簡單的方法有這樣.proto文件結構訪問協議緩衝區領域

{ 
    session{ 
    field1 = value; 
    field2 = value; 
    ... 
    } 
object1{ 
    Object1field1 = value; 
    Object1field2 = value; 
    ... 
} 
object1{ 
    Object1field1 = value; 
    Object1field2 = value; 
    ... 
} 
object2{ 
    Object2field1 = value; 
    Object2field2 = value; 
    ... 
    SubObject1{ 
    SubObject1field1 = value; 
    SubObject2field2 = value; 
    ... 
    } 
} object2{ 
    Object2field1 = value; 
    Object2field2 = value; 
    ... 
    SubObject1{ 
    SubObject1field1 = value; 
    SubObject2field2 = value; 
    ... 
    } 
} 

} 簡單地說,有複雜的層次結構。 Object1或Object2例如可以是可重複的。是否有可能編寫通用方法將返回字段值作爲像int,布爾,字符串,日期時間或只是字符串的基礎對象?我想獲得由字符串字面下面的訪問:

public object GetFieldValue(int number, string fullPath) 

凡FULLPATH可以這樣指定,例如:必要重複場

fullPath = "object1.Object1field1"; 

數量:數量可以等於0,第例如,「object1」和1代表第二個。還需要方法來獲得object1重複計數的字段名稱:

public int GetFieldCount(string fieldName) 

而且也需要類似的方式訪問到子對象的嵌套級別。那可能嗎?是否有替代協議緩衝區硬編碼類?

+0

你目前使用什麼協議緩衝庫? – 2012-04-13 23:10:04

+0

似乎protobuf-csharp端口,他們給我pregenerated類和Google.ProtocolBuffers.dll我的項目。哪一個更適合這樣的任務?這兩個C#協議緩衝區庫文檔和示例都非常少。 – 2012-04-14 09:15:02

+0

我還可以問:在我看來,這樣做的主要方法是反序列化數據,然後使用反射(或類似FastMember)來獲取名稱值。這是一個選項嗎?如果您不知道對象定義,則不能按名稱訪問,因爲protobuf不存儲名稱。 – 2012-04-14 10:16:35

回答

0

嗯......絕對的protobuf-CSHARP端口都有這項任務所需的一切,例如:

IMessage object2 = (IMessage)original[original.DescriptorForType.FindFieldByName("object2"), 0]; 
IMessage subObject1 = (IMessage)object2[object2.DescriptorForType.FindFieldByName("SubObject1")]; 
int value = (int)subObject1[subObject1.DescriptorForType.FindFieldByName("SubObject1Field1")]; 

由於從即時聊天派生的所有類型。會回到它。 ;)

+0

順便說一句,剛剛閱讀版本2.4.1發行說明 - 它允許: - 添加「Google.ProtoBuffers.Serialization」程序集以支持從XML,JSON *讀取和寫入消息。 * IDictionary <,> **等。這是完美的! – 2012-04-17 17:59:35

0

關於xml/protobuf對話;我的瞭解是protobuf-csharp-port使用不可變類型,所以不適用於像XmlSerializer這樣的東西。相反,protobuf-net故意開始使用標準的可變POCO類型,既可以是現有的DTO,也可以是通過protprotogen從.proto生成的;無論哪種方式,我們最終生成的類型一樣的東西:

[ProtoContract] 
public class Foo { 
    [ProtoMember(1)] 
    public string Name {get;set;} 
    [ProtoMember(2)] 
    public Bar Something {get;set;} 
} 
[ProtoContract] 
public class Bar { 
    [ProtoMember(1)] 
    public int Id {get;set;} 
} 

(給予或採取一些複雜性)

然後從protobuf的流XML轉換很簡單:

Foo foo; 
using(var source = ...) { 
    foo = Serializer.Deserialize<Foo>(source); 
} 
string xml; 
using(var sw = new StringWriter()) { 
    var ser = new Serializer(typeof(Foo)); 
    ser.Serialize(sw, foo); 
    xml = sw.ToString(); 
} 

現在xmlFoo實例中的相同數據的XmlSerializer表示(以及諸如Bar的任何子數據)

+0

如果protobuf-net生成這樣的類,那麼我喜歡你的實現更多,將嘗試它而不是protobuf-csharp-port。如果Bar是可重複的,那麼protobuf-net會在你的例子中產生什麼? – 2012-04-16 10:22:52

+0

@AlekseyK'列表' – 2012-04-16 10:26:16

+0

比protobuf-csharp-port更酷更容易使用和理解的數據結構 - 實際上這很糟糕。通過您的protobuf-net,通過反射訪問字段並實現我需要的訪問變得更加容易。 – 2012-04-16 10:59:22

0

順便說一句,如果你伸出你的代碼生成的東西是這樣的:

[ProtoContract] 
public class Foo : IGetFieldsByName { 
    [ProtoMember(1)] 
    public string Name {get;set;} 
    [ProtoMember(2)] 
    public Bar Something {get;set;} 
} 
[ProtoContract] 
public class Bar : IGetFieldsByName { 
    [ProtoMember(1)] 
    public int Id {get;set;} 
} 

即繼承相同的接口的所有類IGetFieldsByName那麼這將是很容易實現的行爲我想:通過「object.name接入領域「文字。你有什麼想法?

+0

我認爲這與協議緩衝區沒有任何關係(protobuf從不使用名稱...)。 – 2012-04-17 03:35:48

+0

我看到了,不過protobuf-csharp-port有一些。請您按照您之前提出的要求,將VS2008(.Net 3.5)的快速成員dll放到Google Code的下載部分? – 2012-04-17 13:36:39

+0

今天我參加了所有會議,但稍後會做 – 2012-04-18 12:18:54