当前位置:编程学习 > 网站相关 >>

我的WCF之旅(5):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的重载(Overloading)

对于.NET重载(Overloading)——定义不同参数列表的同名方法(顺便提一下,我们但可以在参数列表上重载方法,我们甚至可以在返回类型层面来重载我们需要的方法——页就是说,我们可以定义两个具有相同参数列表但不同返回值类型的两个同名的方法。不过这种广义的Overloading不被我们主流的.NET 语言所支持的——C#, VB.NET, 但是对于IL来说,这这种基于返回值类型的Overloading是支持的)。相信大家听得耳朵都要起老茧了。我想大家也清楚在编写传统的XML Web Service的时候,Overloading是不被支持的。

原因很简单,当我们用某种支持.NET的高级语言写成的程序被相应的编译器编译成Assembly的过程中,不单单是我们的Source Code会被变成IL Code,在Assembly中还会生成相应的原数据Metadata——这些Metadata 可以被看看是一张张的Table。这些Table存储了定义了主要3个方面的信息——构成这个Assembly文件的信息;在Assembly中定义的Type及其相关成员的信息;本引用的Assembly 及Type的信息。这些完备的Metadata成就了Assembly的自描述性(Self-Describing),也只是有了这些Metadata,使.NET可以很容易地根据方法参数的列表甚至是返回值得类型来判断调用的究竟了那个方法。

而对于XML Web Service,它的标准实际上是基于XML的,近一步说,一个XML Web Service是通过一个一段XML来描述的,而这个描述XML Web Service的XML,我们称之为WSDL(Web Service Description Language)。在WSDL中,Web Service的一个方法(Method)对应的是一个操作(Operation),Web Service 所有的Operation定义在WSDL中的portType Section。我们可以参照下面一段XML,它是从一个完整的WSDL中截取下来的。我们可以看到,portType包含了Web Service定义的所有Operation,每个Operation由一个operation XML Element表示。看过我前面Blog的读者应该知道,从消息交换(Message Exchange)的层面上讲,一个Operation实际上体现的是一种消息交换的模式(Message Exchange Pattern——MEP)。所以我们完全可以通过一定消息交换的输入消息(Input Message)和输出(Output Message )定义一个Operation。而WSDL也是这样做的。(这里顺便提一下,Output Message部仅仅对应一个方法的Return Value,还包括表明ref 和out的Parameter)。除了定义进行消息交互的Message的格式(一般通过XSD)之外,每个Operation还应该具有一个能够为一标识该Operation的ID,这个ID通过name XML Attribute来定义。通常的情况下,Operation的Name使用Web Service的方法名——这就是在传统XML Web Service不可以使用Overloading的原因。


<wsdl:portType name="ICalculator">
  <wsdl:operation name="AddWithTwoOperands">
    <wsdl:input wsaw:Action="http://tempuri.org/ICalculator/AddWithTwoOperands" message="tns:ICalculator_AddWithTwoOperands_InputMessage" />
    <wsdl:output wsaw:Action="http://tempuri.org/ICalculator/AddWithTwoOperandsResponse" message="tns:ICalculator_AddWithTwoOperands_OutputMessage" />
  </wsdl:operation>
  <wsdl:operation name="AddWithThreeOperands">
    <wsdl:input wsaw:Action="http://tempuri.org/ICalculator/AddWithThreeOperands" message="tns:ICalculator_AddWithThreeOperands_InputMessage" />
    <wsdl:output wsaw:Action="http://tempuri.org/ICalculator/AddWithThreeOperandsResponse" message="tns:ICalculator_AddWithThreeOperands_OutputMessage" />
  </wsdl:operation>
</wsdl:portType>

和XML Web Service,WCF也面临一样的问题——我觉得我们可以把WCF看成.NET平台下新一代的Web Service。虽然现有XML Web Service现在具有广泛的使用——尤其在构建跨平台性的分布是应用和进行系统集成上面,但是从Microsoft已经明确提出WSE 3.0将是最后一个Version的WSE,所以,现有的Web Service将会全面的过渡到WCF。WCF到底是什么东西,我在前面的文章中不断地提出这个问题,在这里我们从 另外一个方面来看待WCF。我们知道W3C定义了一系列关于WS的规范Specification,成为WS-* Specification。这一系列的Specification定义了建立在XML和SOAP标准之上的基于如何将一个可互操作系统(Interoperable System)的各个方面的标准,比如WS-Messaging,WS-Security,WS-Transaction等等。而WCF则可以看成是这一整套Specification的实现。但是这种实现最终还是落实到我们.NET编程上。我们可以把WS-Specification和我们的基于.NET语言的编程看成是两种截然不同的编程模型(Programming Model)。WCF的功能则是把这两种不同的编程模型统一起来,实现他们之间的一个Mapping——可以把WCF看成一个Adapter。

回到我们的Overloading上面来,Overloading是.NET Framework原生支持的。通过Overloading,我们可以使用同名的方法来定义不同的操作,从而使我们的Code显得更加优雅(Elegant)。要是Overloading在WCF中可以使用,WCF必须提供这样的一个Mapping——是被重载的具有相同方法的的方法Mapping到不同的Operation上。而提供着一个功能的就是ServiceContract。下面我们来结合一个Sample来看如何在WCF中使用Overloading。

沿用我们的Calculator的应用,现在我们做一个加法器,它具有两个Operation——两书相加和三数相加。这两个方法都用一个名称Add。

1.下面是Solution的结构。不像前面的结构,这这里我们没有把Service Contract单独提取出来,供Client和Service供用。因为我们现在模拟的是,Service完全由一个外部的第三方提供,Service 已经确定,不能根据Client的具体要求来修改Service。Source Code从这里下载。

\


2.Service端的Code:

Service Contract: Artech.OverloadableContract.Service ICalculator.cs.


using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;

namespace Artech.OverloadableContract.Service
{
    [ServiceContract]
   public interface ICalculator
    {
        [OperationContract(Name = "AddWithTwoOperands")]
       double Add(double x, double y);

       [OperationContract(Name = "AddWithThreeOperands")]
       double Add(double x, double y, double z);
    }
}

这个Service Contract定义了Overloading的两个Add方法,为了把这两个方法映射到两个不同的Operation,我们通过System.ServiceModel.OperationAttribute 的Name属性为Operation指定一个Name——AddWithTwoOperands 和AddWithThreeOperands。

下面是Service的Code,简单地实现了Service Conract,无须赘言。

 

using System;
using System.Collections.Generic;
using System.Text;

namespace Artech.OverloadableContract.Service
{
    public class CalculatorService:ICalculator
    {
        ICalculator Members#region ICalculator Members

        public double Add(double x, double y)
        {
            return x + y;
        }

        public double Add(double x, double y, double z)
        {
            return x + y + z;
        }

        #endregion
    }
}

3.Hosting Service

App.config


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
     
        <behaviors>
            <serviceBehaviors>
                <behavior name="calculatorServiceBehavior">
                    <serviceMetadata httpGet

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,