1. 程式人生 > >在asp.net環境下使用Protocol Buffer

在asp.net環境下使用Protocol Buffer

什麼是Protocol Buffer就不介紹了,網上資料很多,簡單說一下在asp.net環境下的使用。

要想在.net環境下使用,可以選擇Protobuf的.net版本,即Protobuf-net。首先下載Protobuf-net,我使用的是Protobuf-net r640,下載過後直接解壓即可,不用再編譯以生成ProtoGen.exe、Protobuf-net.dll等檔案,因為解壓後文件夾中已經有這些了。接下來,正文開始:

第一種方式:
1.新建一個專案,控制檯或者Web應用程式都可以,然後在專案中引用Protobuf-net.dll。

2.既然要序列化肯定得有要序列化的目標,所以,定義類。

[ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public string Name { get; set; }
    [ProtoMember(2)]
    public int Age { get; set; }
    [ProtoMember(3)]
    public Address address { get; set; }
}

[ProtoContract]
public class Address
{
    [ProtoMember(1)]
    public string Prov { get
; set; } [ProtoMember(2)] public string City { get; set; } }

可以看到在Person類前有ProtoContract特性,類中每個成員前都有ProtoMember特性,需要注意的是,ProtoMember必須有引數,而且引數是唯一的不可重複的整型值,最好從1開始。不同類中ProtoMember的引數沒有關聯,即在各個類中ProtoMember的引數都是從1開始的。

3.序列化和反序列化。

Person p = new Person() { Name = "Kevin", Age = 20, address = new
Address() { Prov = "四川", City = "成都" } }; MemoryStream ms = new MemoryStream(); Serializer.Serialize<Person>(ms, p); string result = Encoding.UTF8.GetString(ms.ToArray());

Serialize方法有很多過載,可以根據實際情況使用。
好了,序列化這樣就完成了。封裝一下使用起來會方便許多:

public class ProtoHelper
{
    //序列化
    public static string Serialize<T>(T t)
    {
        MemoryStream ms = new MemoryStream();
        Serializer.Serialize<T>(ms, t);
        return Encoding.UTF8.GetString(ms.ToArray());
    }

    //反序列化
    public static T DeSerialize<T>(string content)
    {
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(content));
        T t = Serializer.Deserialize<T>(ms);
        return t;
    }
}

試驗一下:

protected void Page_Load(object sender, EventArgs e)
{
    List<Person> list = new List<Person>();
    Person p1 = new Person() { Name = "Leon", Age = 20, address = new Address() { Prov = "四川", City = "成都" } };
    Person p2 = new Person() { Name = "Kevin", Age = 30, address = new Address() { Prov = "廣東", City = "深圳" } };
    list.Add(p1);
    list.Add(p2);
    string s1 = ProtoHelper.Serialize<List<Person>>(list);

    List<Person> list1 = ProtoHelper.DeSerialize<List<Person>>(s1);
    foreach (Person p in list1)
    {
        Response.Write(p.Name + "," + p.Age + "歲," + p.address.Prov + p.address.City + "<br />");
    }
}

成功!

第二種方式:
1.編寫一個.proto檔案,定義協議的格式。
在ProtoGen目錄下有一個descriptor.proto檔案,可以先看看,然後用這個當模板來寫我們自己的Person.proto檔案。那麼開始:

message Person {
    required string Name=1;
    required int32 Age=2;
    required Address address=3;
}

message Address{
    required string Prov=1;
    required string City=2;
}

語法就和定義類差不多,message對應class,required表示不可增加或刪除的欄位,必須初始化;除了required,還有可選欄位optional,可刪除,可以不初始化;repeated可重複欄位。Name=1,Age=2…對應ProtoMember(1),ProtoMember(2)…

2.生成Person.cs檔案。
在cmd中進入ProtoGen資料夾,執行以下命令:

protogen -i:Person.proto -o:Person.cs -ns:UGE.Metadata -p:import=UGE

這句命令的意思是通過Person.proto來生成Person.cs,namespace為UGE.Metadata,引用UGE。檢視Person.cs就能發現,其實就是自動生成了Person和Address兩個類,最終達成的效果和第一種方式是一樣的。什麼?你說第一種方式沒有required,optional或者repeated修飾?那麼這樣就可以了:

[ProtoMember(1), IsRequired = true]
public string Name { get; set; }

3.序列化和反序列化。
方法和第一種方式完全一樣,就不需要多說了。

兩種方式各有優缺點,看情況使用吧!

以上。