WCF分布式开发步步为赢(5)服务契约与操作重载
继上一节WCF分布式开发步步为赢系列的(4):WCF服务可靠性传输配置与编程开发,本节我们继续学习WCF分布式开发步步为赢的第(5)节:服务契约与操作重载。这里我们首先讲解OOP面向对象的编程中方法重载,重载的意义,WCF服务编程开发如何实现操作重载,随后是代码分析部分,给出了服务端服务契约定义和实现操作重载的注意的问题和实现过程,然后详细介绍了客户端实现操作重载的方式。最后是本文的总结部分。本节的结构是:【1】重载概念【2】操作重载【3】代码实现分析【4】运行结果【5】总结
【1】重载概念:
【1.1】什么是重载(OverLoad):
所谓重载是指同一个方法名可以对应着多个方法的实现。这些方法的名字相同,但是方法的参数的类型不同。这就是方法重载的概念。函数方法类和对象的应用尤其重要。
方法重载要求编译器能够唯一地确定调用一个方法时应执行哪个方法代码,即采用哪个方法实现。确定方法实现时,要求从方法参数的个数和类型上来区分。这就是说,进行方法重载时,要求同名方法在参数个数上不同,或者参数类型上不同。否则,将无法实现重载。
关于重载一定要注意:重载方法的参数类型和参数个数一定要不同(即:要么参数的类型不同,要么参数的个数不同,要么参数的类型和个数都不同),否则,编译器就不知道该调用那个方法了。
方法重载的好处就是相同的方法,带来不同的结果和实现,这里我们可以根据传递参数的不同来决定调用飞方法。这是编译时多态的一种实现机制。
【1.2】C#类方法重载示例:
我们这里给出一个简单的c#语言实现的方法重载的列子,这里对于SayHelloOverLoading方法,同一个类里给出的三个方法的参数个数不同。内部实现也不同。具体代码如下:
//3.面向对象里的类,如何实现操作重载,和WCF服务类里的操作重载做对比
public class ClassOverLoading
{
public ClassOverLoading()
{ }
//掩饰方法重载,分别实现三个方法,C#等面向对象的语言提供了方法重载机制的支持。
public string SayHelloOverLoading()
{
//编写代码
return "Hello,This an C# class overloading demo";
}
//类里的方法重载不需要别名
public string SayHelloOverLoading(string name)
{
//编写代码
return "Hello:" + name + "This an C# class overloading demo";
} public string SayHelloOverLoading(string firstName, string lastName) {
//编写代码
return "Hello:" + firstName + lastName + "This an C# class overloading demo";
} }
【2】操作重载:
【2.1】操作重载:
WCF服务支持核心的Web 服务协议,同样其元数据交换也是基于XML语言描述,客户端通过WSDL文件来了解服务方法相关的信息,包括参数的个数、类型、返回值、调用顺序等重要信息。由于WSDL不支持方法的重载,因此我们的WCF服务操作重载就无法通过WSDL暴露给客户端。如果我们在服务契约里定义了方法的重载,编译可以正常通过,但是启动服务宿主就会抛出System.InvalidOperationException异常,如下图:
因此我们不能在WCF服务类了定义和实现方法重载,否则无法暴露为服务操作。
【2.2】解决办法:
WCF给我们提供了一个解决办法,让我们可以在WCF服务类里使用服务操作的重载。WCF定义了一个机制OperationContract,使用OperationContract特性的Name属性,为操作指定别名:
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationContractAttribute : Attribute
{
public string Name
{get;set;} //更多成员 }
【3】代码实现分析:
下面我们来给出一个具体的WCF服务实现操作重载,包括服务定义、宿主配置、客户端引用和测试的完整过程。
【3.1】服务契约:
定义了服务契约IWCFOverLoadingService,分别给出SayHelloOverLoading操作契约的3种不同定义和WCFService服务类里的实现。具体代码如下:
//1.服务契约,操作契约重载
[ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")]
public interface IWCFOverLoadingService
{
//操作契约
[OperationContract(Name = "SayHelloOverLoading1")]
string SayHelloOverLoading();
//操作契约
[OperationContract(Name = "SayHelloOverLoading2")]
string SayHelloOverLoading(string name);
//操作契约
[OperationContract(Name = "SayHelloOverLoading3")]
string SayHelloOverLoading(string firstName, string lastName); }
//2.服务类,集成接口。实现契约
public class WCFService : IWCFOverLoadingService
{
//实现接口定义的方法
public string SayHelloOverLoading()
{
Console.WriteLine("Hello! ,This an overloading demo for WCF Service ");
return "Hello! This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string name)
{
Console.WriteLine("Hello! {0},This an overloading demo WCF Service ", name);
return "Hello! " + name + ", This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string firstName, string lastName)
{
Console.WriteLine("Hello! {0} {1},This an overloading demo WCF Service", firstName, lastName);
return "Hello! " + firstName + " " + lastName + ", This an overloading demo for WCF Service "; ;
}
}
【3.2】托管宿主:
自定义托管宿主使用配置文件来定义服务的终结点和元数据交换节点,服务的交换行为等其他属性也在配置文件里给出,我们配置了三种不同的数据服务通信方式,分别是http、tcp、IPC.具体配置信息如下:
<services>
<service behaviorConfiguration="WCFService.WCFServiceBehavior" name="WCFService.WCFService">
<endpoint
address="http://localhost:9001/WCFService"
binding="wsHttpBinding"
contract="WCFService.IWCFOverLoadingService">
</endpoint>
<endpoint
address="net.tcp://localhost:9002/WCFService"
binding="netTcpBinding"
contract="WCFService.IWCFOverLoadingService">
</endpoint>
<endpoint
address="net.pipe://localhost/WCFService"
binding="netNamedPipeBinding"
contract="WCFService.IWCFOverLoadingService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/"/>
<add baseAddress="net.tcp://localhost:9002/"/>
<add baseAddress="net.pipe://localhost/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.WCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
【3.3】客户端服务引用:
我们来分别添加对服务端的引用,首先启动托管宿主程序。然后使用Visual Studio2008工具直接添加服务引用,你也可以使用svcUtil.exe工具,如图所示:
客户端输入服务的基地址,查找服务,成功够我们可以看到服务契约的信息,这里显示的3个操作名称已经不同,实际上这里给出的是三个不同名称的服务方法。输入命名空间,确定即可完成。
【3.4】代理代码:
客户端反序列化生成的服务契约等信息,我们查看操作契约对应的客户端方法名称以及改变,这样一来,客户端就没有实现对应的方法重载,也就不能使用重载带来的优势,也即是编译时多态的特性。手动更改客户端服务代理类和服务契约代码,使之支持操作方法重载,代码如下:
public interface IWCFOverLoadingService {
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading1" ,Action="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1", ReplyAction="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1Respon" +
"se")]
string SayHelloOverLoading(); [System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading2", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2Respon" +
"se")]
string SayHelloOverLoading(string name); [System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading3", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3Respon" +
"se")]
string SayHelloOverLoading(string firstName, string lastName);
}
这样我们客户端方法也支持操作方法的重载特性。
【3.5】客户端测试代码:
为了测试操作契约,我们在客户端应用里添加了部分的测试代码,这里为了测试服务端定义的不同的操作。我们分组按照协议给出了测试的代码:
//实例化客户端服务代理Tcp
ServiceOverLoadingTcp.WCFOverLoadingServiceClient wcfServiceProxyTcp =
new ServiceOverLoadingTcp.WCFOverLoadingServiceClient("WSHttpBinding_IWCFOverLoadingService1");
Console.WriteLine("Test call service using TCP--------------------.");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Lei", "Xu")); //实例化客户端服务代理Http
ServiceOverLoadingHttp.WCFOverLoadingServiceClient wcfServiceProxyHttp =
new ServiceOverLoadingHttp.WCFOverLoadingServiceClient("NetTcpBinding_IWCFOverLoadingService");
Console.WriteLine("Test call service using Http-------------------");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Lei", "Xu")); //Debuging
Console.WriteLine("Press any key to continue");
Console.Read();
【4】运行结果:
这里分别调用三种服务操作,进行测试。运行的结果如图所示:
【5】总结:
以上就是本节对WCF服务操作重载的介绍,包括一般重载的基本定义和c#语言中简单的方法重载的实现。然后介绍了WCF操作重载的实现机制、局限性和解决办法,服务契约默认不支持操作方法重载,我们可以利用WCF已有的机制给出方法的别名来解决这个问题。然后给出了包括客户端等完整的测试解决方案,客户端反序列话生成服务类默认不支持服务操作方法重载的,生成的也是服务操作的别名方法。我们在客户端要想使服务代理类支持重载,以利用重载的优势,就需要重新修改客户端服务代理代码。 另外给出本节的实例代码供大家参考:
/Files/frank_xl/WCFServiceOverLoadFrankXuLei.rar。
参考资料:
1.《函数重载》:http://baike.baidu.com/view/534068.htm
WCF分布式开发步步为赢(5)服务契约与操作重载的更多相关文章
- WCF分布式开发步步为赢(15):错误契约(FaultContract)与异常处理(ExceptionHandle)
今天学习WCF分布式开发步步为赢系列的15节:错误契约(FaultContract)与异常处理(ExceptionHandle).本节内容作为WCF分布式开发的一个重要知识点,无论在学习还是项目中都应 ...
- WCF分布式开发步步为赢(6):WCF服务契约继承与分解设计
上一节我们学习了WCF分布式开发步步为赢(5)服务契约与操作重载部分.今天我们来继续学习WCF服务契约继承和服务分解设计相关的知识点.WCF服务契约继承有何优势和缺点?实际项目里契约设计有什么原则和依 ...
- WCF分布式开发步步为赢(7):WCF数据契约与序列化
本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为 ...
- WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发
今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...
- WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发
今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们 ...
- WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ
之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识(1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的基础文章.在那篇文章里,我们详细介绍了MSMQ ...
- WCF分布式开发步步为赢(11):WCF流处理(Streaming)机制
WSE3.0框架提供了数据优化传输机制,WSE3.0构建Web服务安全(4):MTOM消息传输优化和文件上传.下载 疑问里进行了介绍.WCF同样也提供了流操作来支持大数据对象的传输和处理优化机制,今天 ...
- WCF分布式开发步步为赢(10):请求应答(Request-Reply)、单向操作(One-Way)、回调操作(Call Back).
WCF除了支持经典的请求应答(Request-Reply)模式外,还提供了什么操作调用模式,他们有什么不同以及我们如何在开发中使用这些操作调用模式.今天本节文章里会详细介绍.WCF分布式开发步步为赢( ...
- WCF分布式开发步步为赢(8):使用数据集(DataSet)、数据表(DataTable)、集合(Collection)传递数据
数据集(DataSet).数据表(DataTable).集合(Collection)概念是.NET FrameWork里提供数据类型,在应用程序编程过程中会经常使用其来作为数据的载体,属于ADO.NE ...
随机推荐
- iOS学习之UIView
一.UI编程概述 1.UI的本意是用户界面,是英文User和Interface的缩写. 2.UI设计则是指对软件的人机交互.操作逻辑.界面美观的整体设计. 3.软件设计可 ...
- 安装Ubuntu 15.10后要做的事
Ubuntu 15.10发布了,带来了很多新特性,同样也依然带着很多不习惯的东西,所以装完系统后还要进行一系列的优化. 1.删除libreoffice libreoffice虽然是开源的,但是Java ...
- Qt使用QStackedWidget实现堆栈窗口
Qt使用QStackedWidget实现堆栈窗口 分类: QT2012-07-25 21:59 6997人阅读 评论(0) 收藏 举报 qtlistsignal 堆栈窗口可以根据选择项的不同显示不同的 ...
- meta 页面元信息定义
禁止页面缓存 1.name属性 name属性主要用于描述网页,与之对应的属性值为content,content中的内容主要是便于搜索引擎机器人查找信息和分类信息用的. meta标签的name属性语法格 ...
- [DHCP服务]——一个验证DHCP原理实验(VMware)
大致实验拓扑图 DHCP Server端的配置 1. 安装DHCP # yum -y install dhcp 2. 拷贝配置文件 # /dhcpd.conf.sample /etc/dhcp/dhc ...
- objective-c自学总结(一)---面向对象
本人大二本科在读,利用一个月多一点的时间对OC语言基础进行了自学,在下一阶段UI学习开始之前, 对这一阶段的自学进行一些总结.在此特别感谢刘晓斌学长和无线互联3G学院 首先说一下对OC的整体感觉,这是 ...
- 微软职位内部推荐-Senior SDE
微软近期Open的职位: Position: Senior SDE-- Mobile Products Android/iOS/WP Senior Developer Contact Person: ...
- jQuery+css3弹出框插件
先来看DEMO:https://codepen.io/jonechen/pen/regjGG 插件的开发很简单,运用了CSS3的动画效果,并且弹出框的内容可以自定义.插件的默认配置参数有三个: var ...
- panel面板
描述:作为承载其他内容的容器的,装载其他组件基础,可折叠.关闭.最大化.最小化和自定义行为.面板可以很容易地嵌入到web页面的任何位置. 其他属性请参考api! 案例1:纯html生成 <div ...
- Java实现文件压缩与解压[zip格式,gzip格式]
Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个文件和任意级联文件夹进行压缩和解压,对于一些初学者来说是个很不错的实例. zip扮演着归档和压缩两个角色:gzip并 ...