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 请求/响应和媒体类型格式化扮演的角色:
下面的代码是自定义的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无疑是一个非常有效的超媒体类型。祝大家龙年新春愉快,吉祥如意!
本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
相关资源:七夕情人节表白HTML源码(两款)