在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.序列化和反序列化。
方法和第一種方式完全一樣,就不需要多說了。
兩種方式各有優缺點,看情況使用吧!
以上。