Protocol Buffers 是在一個很理想的結構化數據的語言中立的序列化格式。你可以考慮一下XML或JSON,但更輕,更小的協議緩沖區。 這種格式的廣應用於谷歌不同的系統之間交換數據。
由於其結構化數據的最佳表現,protocol buffers 是一個代表RESTful服務處理的數據很好的選擇。要遵循REST的原則, protocol buffers 應作為一個新的超媒體類型的代表。 在當前版本(.NET 4) 的Windows通訊基礎(WCF),包含一個新的媒體類型,需要相當數量的努力。 幸運的是,新版本的WCF HTTP堆棧,使媒體類型的WCF編程模型的一等公民,大家可以Glenn Block’s 博客去了解更詳細的內容。推薦大家假期可以看下這本書《REST實戰》http://book.douban.com/subject/6854551/
下面我們來介紹如何使用Google Protocol Buffers,只定義一個超媒體類型 ProtoBufferFormatter:
自定義超媒體類型是通過創建自定義的MediaTypeFormatter,實現OnWritetoStream() 和 OnReadFromStream() 方法進行序列化和反序列化處理。人們經常認為媒體類型只是在服務端使用,但是它用來在客戶端控制序列化和反序列化的要求,下圖顯示了一個HTTP 請求/響應和媒體類型格式化扮演的角色:
這個例子我們使用入門:構建簡單的Web API 的代碼和WCF Web API Preview 6。使用的媒體類型是application/x-protobuf ,REST服務的核心原則就是服務器和客戶端之間的松耦合性,客戶端需要知道書簽的URI,但不應該知道任何其他的URI的知識,但是客戶端必須知道鏈接關系。
下面的代碼是自定義的ProtoBufferFormatter,構造函數里指明了支持的媒體類型 application/x-protobuf。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http.Formatting;
using System.IO;
using ProtoBuf;
using ProtoBuf.Meta;
namespace WcfWebFormat.Formatters
{
public class ProtoBufferFormatter : MediaTypeFormatter
{
public ProtoBufferFormatter()
{
this.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-protobuf"));
}
protected override void OnWriteToStream(Type type, object value, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, System.Net.TransportContext context)
{
Serializer.Serialize(stream, value);
}
protected override object OnReadFromStream(Type type, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders)
{
object obj = (RuntimeTypeModel.Default).Deserialize(stream, null, type);
return obj;
}
}
}
如上所示,我們在OnWriteToStream方法中將.NET對象序列化為ProtoBuf格式,在OnReadFromStream方法中將ProtoBuf格式飯序列化為.NET對象。
現在需要給我們的.NET對象加入ProtoBuf 序列化的標簽:
using System.Collections.Generic;
using System.Xml.Serialization;
using ProtoBuf;
namespace ContactManager.Resources
{
[ProtoContract]
public class Contact
{
[ProtoMember(1)]
public int ContactId { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
}
}
把ProtoBufferFormatter 加入到WCF運行時的超媒體類型集合里。
using Microsoft.ApplicationServer.Http;
using WcfWebFormat.Formatters;
namespace ContactManager
{
public class ContactManagerConfiguration : HttpConfiguration
{
public ContactManagerConfiguration()
{
this.Formatters.Add(new ProtoBufferFormatter());
}
}
}
修改服務配置,使用ContactManagerConfiguration:
var config = new ContactManagerConfiguration() { EnableTestClient = true };
routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory() { Configuration = config }, typeof(ContactsApi)));
在客戶端調用的代碼如下:
var serviceUri = new Uri("http://localhost:9000/api/contacts/");
var httpClient = new HttpClient();
httpClient.BaseAddress = serviceUri;
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-protobuf"));
var response = httpClient.GetAsync("1").Result;
Contact obj = (RuntimeTypeModel.Default).Deserialize(response.Content.ReadAsStreamAsync().Result, null, typeof(Contact)) as Contact;
var formatters = new MediaTypeFormatterCollection() { new ProtoBufferFormatter() };
var content = new ObjectContent<Contact>(obj, "application/x-protobuf",formatters);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf");
httpClient.PostAsync(serviceUri,content);
即使目前來說Google Protocol Buffers沒有XML/JSON那樣普及,RESTful服務使用中ProtoBuf無疑是一個非常有效的超媒體類型。祝大家龍年新春愉快,吉祥如意!
相關文章: