WCF学习笔记--契约

WCF的所有服务都会公开为契约(Contract)。契约与平台无关,是描述服务功能的标准方式。WCF定义了四种类型的契约。

服务契约(Service Contract)

服务契约描述了客户端能够执行的服务操作。服务契约是下一章的主题内容,但书中的每一章都会广泛使用服务契约。

数据契约(Data Contract)

数据契约定义了与服务交互的数据类型。WCF为内建类型如int和string隐式地定义了契约;我们也可以非常便捷地将定制类型定义为数据契约。本书第3章专门介绍了数据契约的定义与使用,在后续章节中也会根据需要使用数据契约。

错误契约(Fault Contract)

错误契约定义了服务抛出的错误,以及服务处理错误和传递错误到客户端的方式。第6章专门介绍了错误契约的定义与使用。

消息契约(Message Contract)

消息契约允许服务直接与消息交互。消息契约可以是类型化的,也可以是非类型化的。如果系统要求互操作性,或者遵循已有消息格式,那么消息契约会非常有用。由于WCF开发者极少使用消息契约,因此本书不会介绍它。

服务契约

ServiceContractAttribute的定义如下:

[AttributeUsage(AttributeTargets.Interface|AttributeTargets.Class,

                Inherited = false)]

public sealed class ServiceContractAttribute : Attribute

{

   public string Name

   {get;set;}

   public string Namespace

   {get;set;}

   //更多成员

}

这个特性允许开发者定义一个服务契约。我们可以将该特性应用到接口或者类类型上,如例1-1所示。

例1-1:定义和实现服务契约

[ServiceContract]

interface IMyContract

{

   [OperationContract]

   string MyMethod(string text);

  

   //不会成为契约的一部分

   string MyOtherMethod(string text);

}

class MyService : IMyContract

{

   public string MyMethod(string text)

   {

      return "Hello " + text;

   }

   public string MyOtherMethod(string text)

   {

      return "Cannot call this method over WCF";

   }

}

ServiceContract特性可以将一个CLR接口(或者通过推断获得的接口,后面将详细介绍)映射为与技术无关的服务契约。ServiceContract特性公开了CLR接口(或者类)作为WCF契约。WCF契约与类型的访问限定无关,因为类型的访问限定属于CLR的概念。即使将ServiceContract特性应用在内部(Internal)接口上,该接口同样会公开为公有服务契约,以便于跨越服务边界实现服务的调用。如果接口没有标记ServiceContract特性,WCF客户端则无法访问它(即使接口是公有的)。这一特点遵循了面向服务的一个原则,即明确的服务边界。为满足这一原则,所有契约必须明确要求:只有接口(或者类)可以被标记为ServiceContract特性,从而被定义为WCF服务,其他类型都不允许。

即使应用了ServiceContract特性,类型的所有成员也不一定就是契约中的一部分。我们必须使用OperationContractAttribute特性显式地标明哪些方法需要暴露为WCF契约中的一部分。OperationContractAttribute的定义如下:

[AttributeUsage(AttributeTargets.Method)]

public sealed class OperationContractAttribute : Attribute

{

   public string Name

   {get;set;}

   //更多成员

}

WCF只允许将OperationContract特性应用到方法上,而不允许应用到同样属于CLR概念的属性、索引器和事件上。WCF只能识别作为逻辑功能的操作(Operation)。通过应用OperationContract特性,可以将契约方法暴露为逻辑操作,使其成为服务契约的一部分。接口(或类)中的其他方法如果没有应用OperationContract特性,则与契约无关。这有利于确保明确的服务边界,为操作自身维护一个明确参与(Opt-In)的模型。此外,契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约。

应用ServiceContract特性

WCF允许将ServiceContract特性应用到接口或类上。当接口应用了Service-Contract特性后,需要定义类实现该接口。总的来讲,我们可以使用C#或VB去实现接口,服务类的代码无需修改,自然而然成为一个WCF服务:

[ServiceContract]

interface IMyContract

{

   [OperationContract]

   string MyMethod();

}

class MyService : IMyContract

{

   public string MyMethod()

   {

      return "Hello WCF";

   }

}

我们可以隐式或显式实现接口:

class MyService : IMyContract

{

   string IMyContract.MyMethod()

   {

      return "Hello WCF";

   }

}

一个单独的类通过继承和实现多个标记了ServiceContract特性的接口,可以支持多个契约。

[ServiceContract]

interface IMyContract

{

   [OperationContract]

   string MyMethod();

}

[ServiceContract]

interface IMyOtherContract

{

   [OperationContract]

   void MyOtherMethod();

}

class MyService : IMyContract,IMyOtherContract

{

   public string MyMethod()

   {...}

   public void MyOtherMethod()

   {...}

}

然而,服务类还有一些实现上的约束。我们要避免使用带参构造函数,因为WCF只能使用默认构造函数。同样,虽然类可以使用内部(internal)的属性、索引器以及静态成员,但WCF客户端却无法访问它们。

WCF允许我们直接将ServiceContract特性应用到服务类上,而不需要首先定义一个单独的契约:

//避免

[ServiceContract]

class MyService

{

   [OperationContract]

   string MyMethod()

   {

      return "Hello WCF";

   }

}

通过服务类的定义,WCF能够推断出契约的定义。至于OperationContract特性,则可以应用到类的任何一个方法上,不管它是私有方法,还是公有方法。

警告:应尽量避免将ServiceContract特性直接应用到服务类上,而应该定义一个单独的契约,这有利于在不同场景下使用契约。

名称与命名空间

可以为契约定义命名空间。契约的命名空间具有与.NET编程相同的目的:确定契约的类型范围,以降低类型的冲突几率。可以使用ServiceContract类型的Namespace属性设置命名空间:

[ServiceContract(Namespace = "MyNamespace")]

interface IMyContract

{...}

若非特别指定,契约的默认命名空间为http://tempuri.org。对外服务的命名空间通常使用公司的URL;至于企业网(Intranet)内部服务的命名空间,则可以定义有意义的唯一名称,例如MyApplication。

在默认情况下,契约公开的名称就是接口名。但是也可以使用ServiceContract特性的Name属性为契约定义别名,从而在客户端的元数据(Metadata)中公开不同的名称:

[ServiceContract(Name = "IMyContract")]

interface IMyOtherContract

{...}

相似的,操作公开的名称默认为方法名,但我们同样可以使用OperationContract特性的Name属性设置别名,从而公开不同的操作名:

[ServiceContract]

interface IMyContract

{

   [OperationContract(Name = "SomeOperation")]

   void MyMethod(string text);

}

原文地址:https://www.cnblogs.com/chhuic/p/1862269.html