Chinaunix首页 | 论坛 | 博客
  • 博客访问: 47143
  • 博文数量: 11
  • 博客积分: 640
  • 博客等级: 上士
  • 技术积分: 175
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-27 23:19
文章分类
文章存档

2011年(1)

2008年(10)

我的朋友

分类: 系统运维

2008-11-23 21:51:14

    这两天把服务契约部分学习完了,写一下自己的一些学习心得。
    首先确定一下几个基本的问题,什么是契约?契约有几种,它们分别有什么用途?契约如何定义?
1.
    任何一个分布式应用程序,它之所以能够互相传递消息,都是事先制定好数据交换规则的,这个规则正是交换数据的双方(比如服务器端和客户端)能彼此理解对方 的依据,WCF作为分布式开发技术的一种,同样具有这样一种特性。而在WCF中制定的的规则就被称之为契约(Contract),它是WCF的消息标准, 是任何一个wcf程序不可或缺的一部分。

2.
契约共有四种,分别介绍如下:

(1)

    用于定义服务操作的服务契约:Service Contract
这种级别的契约又包括两种:ServiceContract和OperationContract

    ServiceContract用于类或者结构上,用于指示WCF此类或者结构能够被远程调用,而OperationContract用于类中的方法(Method)上,用于指示WCF该方法可被远程调用。

(2)

    用于自定义数据结构的数据契约:Data Contract
数据契约也分为两种:DataContract和 DataMember.DataContract用于类或者结构上,指示 WCF此类或者结构能够被序列化并传输,而DataMember只能用在类或者结构的属性(Property)或者字段(Field)上,指示WCF该属 性或者字段能够被序列化传输。

(3)

    用于自定错误异常的异常契约:Fault Contract
FaultContract用于自定义错误异常的处理方式,默认情况下,当服 务端抛出异常的时候,客户端能接收到异常信息的描述,但这些描述往往格式统一,有时比较难以从中获取有用的信息,此时,我们可以自定义异常消息的格式,将 我们关心的消息放到错误消息中传递给客户端,此时需要在方法上添加自定义一个错误消息的类,然后在要处理异常的函数上加上FaultContract,并 将异常信息指示返回为自定义格式。

(4)

    用于控制消息格式的消息契约:Message Contract
简单的说,它能自定义消息格式,包括消息头,消息体,还能指示是否对消息内容进行加密和签名。

3.

    契约的使用是简单的,至少看起来是这样,就是在普通的程序结构上添加一些声明性的属性,如直接在类上声明ServerContractAttribute,则该类就可以被远程客户端访问到,又如在类中方法上申明OperationContractArribute,则可以把方法暴露给远程客户端。至于消息契约和异常契约将相对难一些,本文主要介绍服务契约,其他的内容将在随后的学习中介绍。



下面将开始本次学习笔记的中心内容,我将以知识点的方式写出:

1. 操作重载

    基于WSDL的操作并不支持我们在C++和C#编程语言中的方法操作重载,会在装载服务宿主时抛出InvalidOperationException异常,但是,我们可以利用OperationContract特性的Name属性为操作指定别名,从而手动地启用操作重载。

2. 契约的继承

    服务契约接口支持继承,可以定义一个契约层级,但是ServiceContract特性却不支持继承,需要在接口层级的每级接口都必须显示的标记ServiceContract特性。

[ServiceContract]
interface ISimpleCalculator
{
[OperationContract]
int Add(int arg1,int arg2);
}
[ServiceContract]
interface IScientificCalculator : ISimpleCalculator
{
[OperationContract]
int Multiply(int arg1,int arg2);
}
class MyCalculator : IScientificCalculator
{
public int Add(int arg1,int arg2)
{
return arg1 + arg2;
}
public int Multiply(int arg1,int arg2)
{
return arg1 * arg2;
}
}
当客户端导入一个服务终结点的元数据时,如果该终结点的契约属于接口层级的一部分,则生成的客户端契约不再维持原来的层级关系。相反,它会取消层级,组成一个单独的名称为终结点的契约。但是,如果使用OperationContract特性中的Action与ResponAction属性,那么导入的接口定义仍然可以保留原来定义每个操作的契约名。
最后,一个单独的代理类可以实现导入契约的所有方法,接上程序:
[ServiceContract]
public interface IScientificCalculator
{
[OperationContract(Action = ".../ISimpleCalculator/Add",
ReplyAction = ".../ISimpleCalculator/AddResponse")]
int Add(int arg1,int arg2);

[OperationContract(Action = ".../IScientificCalculator/Multiply",
ReplyAction = ".../IScientificCalculator/MultiplyResponse")]
int Multiply(int arg1,int arg2);
}

public partial class ScientificCalculatorClient :
ClientBase, IScientificCalculator
{
public int Add(int arg1,int arg2)
{...}
public int Multiply(int arg1,int arg2)
{...}
//代理的其余内容
}

客户端可以手工修改代理以及导入契约的定义,恢复契约层级(此部分内容我尚未全部弄明白,暂时先不写,稍后再做修改)

3. 契约分解
契约分解的意义在于使契约包含的操作尽可能的少,达到最小成本。
这里有几个参考性的编码规范:
(1)避免定义只有一个成员的契约
(2)每个服务契约最好只定义三到五个成员
(3)每个服务契约的成员不要超过20个。12个是可能的实际限定。

4. 契约查询是需要应用程序获取服务终结点的元数据,查看是否存在至少一个终结点支持请求的契约。为了简化对返回元数据的解析工作,WCF提供了几个辅助类,位于System.ServiceModel.Description命名空间里。分别有MetadataExchangeClient ,MetadataImporter ,ServiceEndpoint 。
几个辅助类的详细用法可参考《WCF 服务编程》里面有应用示例。




阅读(918) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-11-24 10:23:59

赞魏刚!贡献了很多原创的好博文