分类: 系统运维
2008-11-23 21:51:14
(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 服务编程》里面有应用示例。