在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的架构的可扩展性,针对一些特殊情况, ...
随机推荐
- 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。
今天安装了一个PDF阅读器,免费的,你懂的,结果自己安装的时候没有将默认的选项取消,就被hao123流氓网站劫持啦. 说实话某免费PDF阅读器还算好的,有一个可以供你选择的项.不想某些软件直接就默认选 ...
- RabbitMQ + PHP (一)入门与安装
RabbitMQ: 1.是实现AMQP(高级消息队列协议)的消息中间件的一种. 2.主要是为了实现系统之间的双向解耦而实现的.当生产者大量产生数据时,消费者无法快速消费,那么需要一个中间层.保存这个数 ...
- hibernate的基本xml文件配置
需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- Android手机相册的布局
实现类似下面的这种布局的方法
- Tomcat 部署我的第一个程序
idea 生成war包.先双击clean,再双击package.生成成功之后就会产生war包. 第二步:将生成好的war文件复制到tomcat文件夹下. 第三步:配置tomcat的server.xml ...
- Oracle创建表空间
1.创建表空间 导出Oracle数据的指令:/orcl file=C:\jds.dmp owner=jds 导入Oracle数据的指令:imp zcl:/orcl file=C:\jds.dmp fu ...
- Centos 6.6 下搭建php5.2.17+Zend Optimizer3.3.9+Jexus环境
(为何安装php5.2.17这个版本 因为phpweb这个程序用到了Zend Optimizer3.3.9 这个东东已经停止更新了 最高支持5.2版本的php 所以就有了一晚上填坑的自己和总结了这篇文 ...
- php杂记(二)
1.获取客户端真实IP if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $onlineip = $_SERVER['HTTP_CLIENT_IP']; } else ...
- 自定义tabBar
★★★★自定义tabBar★★★★★★★ Demo下载地址:https://github.com/marlonxlj/tabBarCustom.git 前言: 有的时候需求要对tabBar进行自定义的 ...