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

时间: 2024-10-09 17:06:46

WCF分布式开发步步为赢(5)服务契约与操作重载的相关文章

WCF分布式开发步步为赢(15):错误契约(FaultContract)与异常处理(ExceptionHandle)

今天学习WCF分布式开发步步为赢系列的15节:错误契约(FaultContract)与异常处理(ExceptionHandle).本节内容作为WCF分布式开发的一个重要知识点,无论在学习还是项目中都应该有所了解.此前也和多位学习爱好者讨论过WCF异常处理的相关知识.这里就系统整理一下,共大家参考.同时也是对<WCF分布式开发步步为赢>系列文章的完善和补充.   本节主要涉及的知识点就是:[1].NET异常处理[2]WCF异常处理[3]错误契约[4]WCF异常处理扩展[5]示例代码分析,最后是[

WCF分布式开发步步为赢(6):WCF服务契约继承与分解设计

上一节我们学习了WCF分布式开发步步为赢(5)服务契约与操作重载部分.今天我们来继续学习WCF服务契约继承和服务分解设计相关的知识点.WCF服务契约继承有何优势和缺点?实际项目里契约设计有什么原则和依据?面向对象的设计经验有何值得借鉴的地方?这里我们会一一给出详细的介绍.本文首先介绍的是WCF服务中契约继承的一些概念.例子代码分析,其次来讲解服务契约的设计问题.首先介绍的也是进行服务设计的必要性,服务设计的原则,示例代码分析.最后是全文的总结部分.结构如下:[1]OO面向对象设计原则,[2]服务

WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发

今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出,具体的WCF绑定协议和可靠性的关系,实现可靠性传输有什么方式,以及配置和开发的详细实现代码分析部分.[1]可靠性传输[2]配置方式实现可靠性传输[3]编程方式实现可靠性传输[4]编程实现必备有序传递[5]结果分析和总结. 下面进入正式的内容: [1]可靠性传输: [1.0]网络协议基础知识: 这里

WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ

之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识(1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的基础文章.在那篇文章里,我们详细介绍了MSMQ消息队列的基本概念.安装.部署.开发.调试等相关问题.今天我们来学习WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ.在WCF框架下使用MSMQ消息队列服务编程.  这里我会给出一个使用WCF MSMQ实现离线请求的DEMO示例程序. 全文结构是:[1]MSMQ基本概念[2]W

WCF分布式开发步步为赢(7):WCF数据契约与序列化

本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为什么会有序列化机制?或者说它是为了解决什么问题?作用是什么?现有的.NET 序列化机制和WCF序列化机制有什么不同?我们在本节文章里都会详细介绍.本节结构:[0]数据契约[1]序列化基本概念[2].NET 序列化机制[3]WCF序列化机制[4]代码实现与分析[5]总结. 下面我们正式进入今天的学习阶

WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发

今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们来详细学习WCF服务元数据交换的相关内容.WCF服务元数据究竟是什么?为什么WCF服务要暴露元数据交换节点?这些和以前的Web Service有什么关系?WCF服务元数据交换的方式有那些?我们如何实现WCF服务元数据交换,本节我们会详细讲解.全文结构如下:[1]WCF服务元数据的基本概念.[2]WC

WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程

今天我们继续学习WCF分布式开发步步为赢系列的12节:WCF事务机制(Transaction)和分布式事务编程.众所周知,应用系统开发过程中,事务是一个重要的概念.它是保证数据与服务可靠性的重要机制. 作为面向服务应用的开发平台,WCF也提供了对事物编程模型的支持..NET 2.0提供的System.Transactions类来开发事务应用程序.同样WCF也支持事务特性,WCF事务机制是什么,它与微软已有的技术如Microsoft 分布式事务协调器 (MSDTC)有何关系?与Enterpise

WCF分布式开发步步为赢(10):请求应答(Request-Reply)、单向操作(One-Way)、回调操作(Call Back).

WCF除了支持经典的请求应答(Request-Reply)模式外,还提供了什么操作调用模式,他们有什么不同以及我们如何在开发中使用这些操作调用模式.今天本节文章里会详细介绍.WCF分布式开发步步为赢(10):请求应答(Request-Reply).单向操作(One-Way).回调操作(Call Back).本文结构:[1]请求应答(Request-Reply).[2]单向操作(One-Way).[3]回调操作(Call Back).[4]示例代码分析.[5]总结.最后上传本文的示例代码. WCF

WCF分布式开发步步为赢(1):WCF分布式框架基础概念

众所周知,系统间的低耦合一直是大型企业应用系统集成追寻的目标,SOA面向服务架构的出现为我们的如何利用现有企业系统资源进行企业ERP系统设计和实现提供了重要的参考原则.SOA如此炙手可热,各大厂商都推出了自己的中间件产品,比如Oracle Fusion和 SAP NetWeaver,IBM.BEA等企业也推出了自己基于SOA的解决方案.基于J2EE平台的SOA架构设计中的一个重要概念就是EJB企业服务总线,作用是实现各个系统的数据交互.而.NET平台上,WCF就是微软为各个系统的数据交互提供通讯