标签:
ProtoBuf有着超高的传输效率, 可以替代WCF的xml和二进制编码, 可以试一试
在VS2013中新建一个 WCF服务库, 名字使用默认的WcfServiceLibrary1
在当前解决方案再新建一个Console程序, 名字叫Client
使用nuget安装proto-net, 为什么不用最新的 2.1.0 版本呢? 因为要弹出错误 protobuf-net”已拥有为“NETStandard.Library”定义的依赖项。
Install-Package protobuf-net -Version 2.0.0.668 -ProjectName WcfServiceLibrary1
Install-Package protobuf-net -Version 2.0.0.668 -ProjectName Client
将WcfServiceLibrary1\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll拷贝到
\WcfServiceLibrary1\WcfServiceLibrary1
WcfServiceLibrary1\Client
注册 行为扩展: 将下面的代码拷贝到<system.serviceModel>下面
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</behaviorExtensions>
</extensions>
将 行为扩展 应用在 终结点行为 上: 在<behaviors>下面拷贝
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf/>
</behavior>
</endpointBehaviors>
还有就是让服务使用这个终结点行为, 在 <endpoint> 下添加
behaviorConfiguration="protoEndpointBehavior"
App.config最终样子
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</behaviorExtensions>
</extensions>
<services>
<service name="WcfServiceLibrary1.Service1">
<endpoint address="" behaviorConfiguration="protoEndpointBehavior"
binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
配置文件写好了后, 还需要修改IServer.cs, 这里只是介绍, 只将 CompositeType 作为例子, 需要添加ProtoContract、ProtoMember 两种特性
[DataContract]
[ProtoContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
[ProtoMember(1)]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
[ProtoMember(2)]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
public interface IService1 也要添加 [ServiceContract] 特性
客户端引用WCF服务, 因为WCF服务就在本项目, 所以要选择解决方案中的服务
客户端也要增加刚才的扩展和终结点行为, 最终App.config 是这样的
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</behaviorExtensions>
</extensions>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/"
behaviorConfiguration="protoEndpointBehavior" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
name="BasicHttpBinding_IService1" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
好了, 可以在客户端调用服务了
static void Main(string[] args)
{
var proxy =new ServiceReference1.Service1Client();
var result=proxy.GetDataUsingDataContract(new ServiceReference1.CompositeType(){ StringValue="test });
Console.WriteLine(result.StringValue);
}
可得到结果是null
查看别人的博文, 原来protobuf 不是WCF的嫡出, 通过服务引用, 并不会像DataMember这种原生支持的Attribute那样, 把ProtoMember传输到Client的自动生成代码里, 所以还需要手工添加, 蛋疼啊
在打开的Reference.cs中找到属性 public bool BoolValue 添加 ProtoMember(1)]
找到属性 public string StringValue 添加 [ProtoMember(2)]
这下终于有结果了
后记, protobuf 并不是为WCF准备的, 而是应该与 gRPC 配合使用, 在 gRPC 的示例文档中可以看到如将一个非常简单的 .proto文件编译成复杂的cs文件, 然后分别被服务端和客户端引用, 最终实现远程调用, 不过示例环境是VS2015
代码
标签:
原文地址:http://www.cnblogs.com/zhouandke/p/5933351.html