代码改变世界

WCF之旅——2 Contract

2007-12-27 21:56  Jun1st  阅读(2129)  评论(3编辑  收藏  举报

1.ServiceContract&OperationContract General

Contract定义了这一个Service能提供什么样的功能和服务(ServiceContract),也告诉了调用这一Service的客户端或者其它的Service在调用时需要提供什么样的参数信息(DataContract)。因此,在SOA架构的系统中,Contract的定义是重中之重。本文将对ServiceContract做一个简单的介绍。

在WCF中,给一个interface(或者class)添加一个[ServiceContract]的Attribute, 这个interface就成为一个面向服务的contract(service-oriented contract)。你可以使用你自己喜欢的变成语言来写这个interface,比如C#, C++, VB.Net等。只要它符合.net framework的CTS(Common Type Specification)。SeriveContract使得一个interface成为一个WCF的contract, 而不再具有类型的可见性(type’s visibility)这一属性。成为一个contract之后,它就成为一个共有的service contract. 而普通的interface对于WCF Service的调用者来说,完全是透明的的,也根本就不知道这个interface的存在。

一个interface要成一个WCF的Contract,需要给这个interface加上[ServiceContract]这一个特性(Attribute),而要这个contract成为一个有用的contract, 还需要给这个interface中希望暴露的方法加上[OperationContract]这一特性。否者,这个interface中所有的方法,对于调用这个service的client来说,都是不可见的。

Eg:

[ServiceContract]
interface IMyContract1
{
   [OperationContract]
   string MyMethod1( );
}
[ServiceContract]
interface IMyContract2
{
   [OperationContract]
   void MyMethod2( );
}

class MyService : IMyContract1,IMyContract2
{
   public string MyMethod1( )
   {...}
   public void MyMethod2( )
   {...}
}

从示例代码钟还可以看出,WCF的多重实现(Multiple Implementation )。

 

2.OperationContract之Operation重载

WCF Contract的实现也支持重载,只不过需要做一些额外的工作。

//Invalid contract definition:
[ServiceContract]
interface ICalculator
{
   [OperationContract]
   int Add(int arg1,int arg2);

   [OperationContract]
   double Add(double arg1,double arg2);
}

运行上面的代码会在ServiceHost加载service的时候抛出一个:InvalidOperationException。

WCF对一个Operation提供了一个叫做Name的Attribute, 利用这个Name可以实现重载,如:

[ServiceContract]
interface ICalculator
{
   [OperationContract(Name = "AddInt")]
   int Add(int arg1,int arg2);

   [OperationContract(Name = "AddDouble")]
   double Add(double arg1,double arg2);
}

只不过有一个不足之处是生成的Proxy的代码相应的函数名将会是AddInt和AddDouble。不过你要是愿意的话可以手动修改生成的函数,但是要确保调用了正确的internal proxy的方法。

3.ServiceContract之继承

WCF Contracts之间支持继承等操作,因此可以建立一个具有层级关系的Contracts。但是[ServiceContract]这一特性不能被继承,因此必须在每一个interface上加上这一特性。

[ServiceContract]
interface ICalculator
{
   [OperationContract]
   int Add(int arg1,int arg2);
}
[ServiceContract]
interface IMyCalculator : ICalculator
{
   [OperationContract]
   int Multiply(int arg1,int arg2);
}

但是当把IMyCalculator这个Service暴露给Client, 并用工具生成Proxy代码时,生成大代码将不具有这种层级关系。这个问题下次说一下。