在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的架构的可扩展性,针对一些特殊情况, ...
随机推荐
- 易用BPM时代,企业如何轻松驾驭H3?
众所周知,BPM作为企业发展的推动力,能敏捷高效的融合业务流程和信息资源.通过综合考虑流程的成本.效率.质量等方面因素,用IT系统将调整后的流程固化下来,从而降低企业管理成本,提高内部运营效率,提升企 ...
- charles工具抓包教程(http跟https)
1.下载charles 可以去charles官网下载,下载地址:http://www.charlesproxy.com/download/ 根据自己的操作系统下载对应的版本,然后进行安装,然后打 ...
- 个人也能申请微信小程序获得APPID和手机测试效果
微信小程序昨晚火爆公测,我也第一时间注册了小程序账号开启公测之旅. 注册过程可以看文档:https://my.oschina.net/imhoodoo/blog/780901 进入后台之后我们其实主要 ...
- ASP.Net MVC 5 in Xamarin Studio 5.2
Xamarin Studio 是一个Mono的跨平台 IDE(Integrated Development Environment),支持Wiindow和Mac,最新发布的5.2 版本支持ASP.NE ...
- Dubbo 备注
Dubbo是阿里开源的一款服务治理中间件,主要包含如下节点: Provider: 暴露服务的服务提供方. Consumer: 调用远程服务的服务消费方. Registry: 服务注册与发现的注册中心. ...
- .NET基础拾遗(7)Web Service的开发与应用基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...
- salesforce 零基础学习(六十)Wizard样式创建数据
项目中表之间关联关系特别多,比如三个表中A,B,C C作为主表,A,B作为从表,有时候C表需要创建数据时,同时需要创建A,B两个表的数据,这种情况下,使用Wizard样式会更加友好. 以Goods_ ...
- hadoop2.7.1 HA安装部署(转)
hadoop集群规划 目标:创建2个NameNode,做高可用,一个NameNode挂掉,另一个能够启动:一个运行Yarn,3台DataNode,3台Zookeeper集群,做高可用. 在 hadoo ...
- PHP 面向对象编程和设计模式 (2/5) - 静态变量、属性和方法及延迟绑定
PHP高级程序设计 学习笔记 2014.06.10 Static(静态)关键字用来定义静态方法和属性,static 也可用于定义静态变量以及后期静态绑定. 1.静态变量 static variable ...
- boost::function的用法
本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1. 介绍 Boost.Func ...