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替代默认的序列化器的更多相关文章

  1. 跟我一起学WCF(8)——WCF中Session、实例管理详解

    一.引言 由前面几篇博文我们知道,WCF是微软基于SOA建立的一套在分布式环境中各个相对独立的应用进行交流(Communication)的框架,它实现了最新的基于WS-*规范.按照SOA的原则,相对独 ...

  2. wcf中的使用全双工通信

    wcf中的契约通信默认是请求恢复的方式,当客户端发出请求后,一直到服务端回复时,才可以继续执行下面的代码. 除了使用请求应答方式的通信外,还可以使用全双工.下面给出例子: 1.添加一个wcf类库 2. ...

  3. wcf中的使用全双工通信(转)

    wcf中的使用全双工通信   wcf中的契约通信默认是请求恢复的方式,当客户端发出请求后,一直到服务端回复时,才可以继续执行下面的代码. 除了使用请求应答方式的通信外,还可以使用全双工.下面给出例子: ...

  4. wcf中的消息模式

    1请求响应模式 a.wcf中的消息模式默认是请求响应模式 b.返回值是void默认也是请求响应模式,可返回服务端的错误信息 c.客户端在请求后,当前线程停止真到接受收服务器的响应 [Opereatio ...

  5. 在 WCF 中使用高效的 BinaryFormatter 序列化

    本文将定义一个 WCF 终结点行为扩展,以在 WCF 中使用更高效的 BinaryFormatter 进行二进制序列化,并实现对是否使用传统二进制序列化功能的可配置. 介绍 实现步骤 使用方法 效果 ...

  6. WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

    原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...

  7. 浅议Grpc传输机制和WCF中的回调机制的代码迁移

    浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...

  8. 十五天精通WCF——第十二天 说说wcf中的那几种序列化

    我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的过程,也就是将参数序列化为message,这篇 我们就来说说这里的序列化,蛮有意思的,可能初学者也明白,在wcf ...

  9. WCF初探-22:WCF中使用Message类(上)

    前言 从我们学习WCF以来,就一直强调WCF是基于消息的通信机制.但是由于WCF给我们做了高级封装,以至于我们在使用WCF的时候很少了解到消息的内部机制.由于WCF的架构的可扩展性,针对一些特殊情况, ...

随机推荐

  1. 著名ERP厂商的SSO单点登录解决方案介绍一

          SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...

  2. 在Linux上运行ASP.NET vNext

    最新的ASP.NET vNext完全开源且可以跨多个平台运行,在Windows环境下我尝试了下,几乎没花什么工夫就跑起了Sample,而在Linux环境下则要多花了不少时间,所以特别记录下整个过程,希 ...

  3. 不得不知的CLR中的GC

    引言 GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上.其实很多语言也有类似的东东, 如Java也有JIT 等等 GC基本概念 垃圾回收机制的算法有好多种 ...

  4. APUE fig 1.10示例代码的完善--对提示符及输入回车的优化

    APUE 第3版第15页的shell2.c示例程序,运行效果如下: gcc ol.shell.c -o origin_shell ./origin_shell % date 2015年12月13日 星 ...

  5. MySQL基础之存储过程

    学过之后却没有总结,今天好不容易有点时间来看看. 存储过程的优势 1.简化复杂的SQL语句,将多个SQL语句封装成为一个存储过程,可以在其中加上一些流程控制语句 2.存储过程封装在数据库内部,编译之后 ...

  6. MailKit---状态更改和删除

    当我们拉取邮件列表,并展示邮件后需要打开邮件,同时标识本邮件状态为已读状态,或者我们直接删除邮件.下面介绍基本的应用. 首先了解邮件的所有枚举状态:MailKit.MessageFlags包括:(No ...

  7. iOS 地图定位及大头针的基本使用

    地图 Part1 - 定位及大头针的基本使用 一.MapKit 作用 : 用于地图展示 如大头针,路线,覆盖层展示等(着重界面展示) 使用步骤 导入头文件 #import <MapKit/Map ...

  8. Git异常:fatal: could not create work tree dir 'XXX': No such file or directory

    GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...

  9. 【WPF】运用MEF实现窗口的动态扩展

    若干年前,老周写了几篇有关MEF的烂文,简单地说,MEF是一种动态扩展技术,比如可以指定以某个程序集或某个目录为搜索范围,应用程序在运行时会自动搜索符合条件的类型,并自动完成导入,这样做的好处是,主程 ...

  10. 【原】SDWebImage源码阅读(四)

    [原]SDWebImage源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 SDWebImage中主要实现了NSURLConnectionDataDelega ...