在Wcf中应用ProtoBuf替代默认的序列化器
Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wcf有一天能在Linux平台上闪瞎所有人。现在简单表述下Wcf中应用ProtoBuf替代默认的序列化器。
准备:
首先,新建一套Wcf的解决方案,包含服务,宿主外加两个客户端用来测试调用:

Wcf_ProtoBufSample.ClientViaMetaData会通过添加服务引用的方式调用服务,Wcf_ProtoBufSample.ClientViaReference则直接通过对Wcf_ProtoBufSample.Service添加引用来调动服务。
分别为每个项目对protobuf-net添加引用: install-package protobuf-net -Version 2.0.0.668(此处现在比较纠结,protobuf-net的最新版本是2.1.0.0,但现在移除了ProtoBuf.ServiceModel,目测是为了兼容dotnet core,估计以后还会再回来的。)
接下来在Wcf_ProtoBufSample.Service中简单定义个服务:
[ServiceContract, ProtoContract]
public interface IGreeterService
{
[OperationContract]
Reply Get(Request request);
}
public class GreeterService : IGreeterService
{
public Reply Get(Request request)
{
Reply reply = new Reply() { GreetInfo = "你好!" + request.Name + ",恭喜你" + request.Age + "岁了!" };
return reply;
}
}
[DataContract]
[ProtoContract]
public class Request
{
[DataMember(Order = )]
[ProtoMember()]
public string Name { set; get; }
[DataMember(Order = )]
[ProtoMember()]
public int Age { set; get; }
}
[DataContract]
[ProtoContract]
public class Reply
{
[DataMember(Order = )]
[ProtoMember()]
public string GreetInfo { set; get; }
}
代码中对DataMember添加了Order的特性,方便过会用。
配置宿主
在宿主中进行配置:
<system.serviceModel>
<services>
<service behaviorConfiguration="GreeterServiceBehavior" name="Wcf_ProtoBufSample.Service.GreeterService">
<endpoint
address="net.tcp://127.0.0.1:6978/GreeterService"
binding="netTcpBinding"
behaviorConfiguration="protoEndpointBehavior"
bindingConfiguration="DefaultTcpBinding"
contract="Wcf_ProtoBufSample.Service.IGreeterService">
</endpoint>
<endpoint
address="net.tcp://127.0.0.1:6976/mex"
binding="mexTcpBinding"
contract="IMetadataExchange">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="GreeterServiceBehavior">
<serviceMetadata/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
</behaviorExtensions>
</extensions>
<bindings>
<netTcpBinding>
<binding name="DefaultTcpBinding"
closeTimeout="00:00:30"
openTimeout="00:00:30"
receiveTimeout="00:05:00"
sendTimeout="00:50:00"
transactionFlow="true"
transferMode="Buffered"
listenBacklog=""
maxBufferPoolSize=""
maxBufferSize=""
maxConnections=""
maxReceivedMessageSize="" >
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
共享元数据的方式调用
然后在Wcf_ProtoBufSample.ClientViaReference项目中添加对Wcf_ProtoBufSample.Service的引用并配置客户端的调用信息:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="DefaultTcpBinding"
closeTimeout="00:00:30"
openTimeout="00:00:30"
receiveTimeout="00:05:00"
sendTimeout="00:50:00"
transactionFlow="true"
transferMode="Buffered"
listenBacklog=""
maxBufferPoolSize=""
maxBufferSize=""
maxConnections=""
maxReceivedMessageSize="" >
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
</behaviorExtensions>
</extensions>
<client>
<endpoint address="net.tcp://127.0.0.1:6978/GreeterService"
binding="netTcpBinding"
bindingConfiguration="DefaultTcpBinding"
contract="Wcf_ProtoBufSample.Service.IGreeterService"
behaviorConfiguration="protoEndpointBehavior"
name="GreeterService">
</endpoint>
</client>
</system.serviceModel>
简单测试一下:
ChannelFactory<IGreeterService> factory = new ChannelFactory<IGreeterService>("GreeterService");
IGreeterService client = factory.CreateChannel();
var res = client.Get(new Request() {Name = "liam",Age = });
Console.WriteLine(res.GreetInfo);
Console.ReadKey();

通过添加服务引用或者WcfUtil
添加服务引用才是我们的最爱,简单快捷,易于维护:
在Wcf_ProtoBufSample.ClientViaMetaData中右键添加服务引用,这里我公开的地址是:net.tcp://127.0.0.1:6976/mex,

拿过来直接用肯定是不行的,毕竟我们已经修改了默认的序列化器,所以在配置中添加对ProtoBuf的配置信息,所以还是需要在配置中引用ProtoBuf的配置的:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IGreeterService" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://127.0.0.1:6978/GreeterService"
behaviorConfiguration="protoEndpointBehavior"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IGreeterService"
contract="ServiceReference.IGreeterService"
name="NetTcpBinding_IGreeterService">
<identity>
<userPrincipalName value="DESKTOP-078UA43\admin" />
</identity>
</endpoint>
</client>
<behaviors>
<serviceBehaviors>
<behavior name="GreeterServiceBehavior">
<serviceMetadata/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
简单调用一下进行测试:
GreeterServiceClient client=new GreeterServiceClient("NetTcpBinding_IGreeterService");
var res = client.Get(new Request() { Name = "liam", Age = });
Console.WriteLine(res.GreetInfo);
运行后发现报错了!

细致一些就不难发现,尽管我们的代理类生成的很简单快捷,但公开元数据的描述不会包含ProtoBuf特性的描述,所以此时我们定义的 [DataMember(Order = 0)]的Order属性此时就要发光发热了!接下来要修改的就是生成的代理类,添加ProtoBuf的序列号特性,在类上标注ProtoContract特性在属性上标注ProtoMember的特性,而且可以看着Order的顺序就行标注:

ProtoBuf的序列化是有顺序的,所以为了保证与服务端一致,此处需要谨慎(此处需要注意,更新服务引用小心自己定义的属性被覆盖)
简单测试:

Over!
(备注:貌似这么做比较复杂,毕竟开源的项目还是挺多的:https://github.com/maingi4/ProtoBuf.Services)
在Wcf中应用ProtoBuf替代默认的序列化器的更多相关文章
- 跟我一起学WCF(8)——WCF中Session、实例管理详解
一.引言 由前面几篇博文我们知道,WCF是微软基于SOA建立的一套在分布式环境中各个相对独立的应用进行交流(Communication)的框架,它实现了最新的基于WS-*规范.按照SOA的原则,相对独 ...
- wcf中的使用全双工通信
wcf中的契约通信默认是请求恢复的方式,当客户端发出请求后,一直到服务端回复时,才可以继续执行下面的代码. 除了使用请求应答方式的通信外,还可以使用全双工.下面给出例子: 1.添加一个wcf类库 2. ...
- wcf中的使用全双工通信(转)
wcf中的使用全双工通信 wcf中的契约通信默认是请求恢复的方式,当客户端发出请求后,一直到服务端回复时,才可以继续执行下面的代码. 除了使用请求应答方式的通信外,还可以使用全双工.下面给出例子: ...
- wcf中的消息模式
1请求响应模式 a.wcf中的消息模式默认是请求响应模式 b.返回值是void默认也是请求响应模式,可返回服务端的错误信息 c.客户端在请求后,当前线程停止真到接受收服务器的响应 [Opereatio ...
- 在 WCF 中使用高效的 BinaryFormatter 序列化
本文将定义一个 WCF 终结点行为扩展,以在 WCF 中使用更高效的 BinaryFormatter 进行二进制序列化,并实现对是否使用传统二进制序列化功能的可配置. 介绍 实现步骤 使用方法 效果 ...
- WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)
原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...
- 浅议Grpc传输机制和WCF中的回调机制的代码迁移
浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...
- 十五天精通WCF——第十二天 说说wcf中的那几种序列化
我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的过程,也就是将参数序列化为message,这篇 我们就来说说这里的序列化,蛮有意思的,可能初学者也明白,在wcf ...
- WCF初探-22:WCF中使用Message类(上)
前言 从我们学习WCF以来,就一直强调WCF是基于消息的通信机制.但是由于WCF给我们做了高级封装,以至于我们在使用WCF的时候很少了解到消息的内部机制.由于WCF的架构的可扩展性,针对一些特殊情况, ...
随机推荐
- 2016/12/31_Python
今天学习主要内容: Python: 1.with语句(补充昨天的文件操作) 用with打开的文件在脚本结束会自动关闭,以防普通打开方式忘记关闭文件连接 语法: with open("demo ...
- IT持续集成之质量管理
研发工具生态 质量相关工作 一次编译产出测试包与上线包 !从源头保证版本的⼀一致性!代码质量控制! 全⽅方位的⾃自动化测试体系保证! 提测冒烟效率! 全⾃自动上线流程杜绝⼈人⼯工犯错! 生产环境应⽤用 ...
- 关于DDD的学习资料汇总
DDD(Domain-Driven Design)领域驱动设计,第一次看到DDD是在学习ABP时,在其中的介绍中看到的.what,DDD是个什么鬼,我不是小白,是大白,没听过.于是乎,度娘查查查,找到 ...
- MementoPattern(备忘录模式)
/** * 备忘录模式 * @author TMAC-J * 用于存储bean的状态 */ public class MementoPattern { public class Memento{ pr ...
- 手机web如何实现多平台分享
话说App一般都带有分享到社交平台的入口,web网页的分享也有很不错的框架,但是随着HTML5的不断发展,手机web页面越来越多的进入到我们的生活中,那如何在我们的手机上完成分享呢?话说各大分享平台都 ...
- Tomcat 部署我的第一个程序
idea 生成war包.先双击clean,再双击package.生成成功之后就会产生war包. 第二步:将生成好的war文件复制到tomcat文件夹下. 第三步:配置tomcat的server.xml ...
- ASP.NET 5 (vNext) Linux部署
引言 工欲善其事,必先利其器. 首先,我们先明确下以下基本概念 Linux相关 Ubuntu Ubuntu是基于linux的免费开源桌面PC操作系统 十分契合英特尔的超极本定位 支持x86.64位和p ...
- 让MacBook识别noppoo mini 84
让MacBook识别noppoo mini 84 noppoo默认是没有mac驱动的,需要下载一个IOUSBHIDDriverDescriptorOverride否则无法noppoo的键位是识别错误的 ...
- Android点击列表后弹出输入框,所点击项自动滚动到输入框上方
使用微信的朋友圈会发现,点击某一条评论后输入框会弹出来,然后所点击的那一项会自动地滚动到输入框上方的位置,这样如果开始所点击的评论在屏幕很下方的话,就不会被输入框遮住,虽然微信这一点在我的MX2频繁点 ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...