1.什么是契约?
契约就是一种双方或者多方的协议,利益相关方就某个问题达成的一种共识,契约确保了服务的正常调用,可以这样理解:客户端以契约的方式进行服务调用,而服务则需要按照契约规定的方式提供服务。 一旦违约势必影响契约双方的正常交互。
契约是服务提供的一组操作的描述。
从功能上讲,每个操作都对应某个具体功能的实现,以及调用这个操作的输入和输出;
从消息交换层面上讲,每个操作定义了所采用的消息交换模式和消息本身的结构。
2.接口
从某种意义上讲,契约和接口几乎可以画上等号,因为在实际中客户对服务可能提出各种变化,虽然可预见,但绝大部分是不可预期的。从交互的角度讲,交互的目的可以看成一种“服务的消费”,即一方消费另一方提供的服务,那么“不变”的就是服务或功能本身,“易变”的就是服务或功能的具体实现。
3.WSDL、XSD与服务契约
服务契约涉及的参与者就是服务提供者和服务的消费者,服务提供者通过服务契约的形式将服务公布出来,服务消费者通过服务契约进行服务消费,要保证服务的正常消费,一个根本的前提就是服务消费者能够正确理解服务提供者公布出来的服务契约。
如何理解?如果希望服务契约被不同平台的客户所理解,就应该以一种平台无关的标准进行描述,作为服务描述的一部分,一份WSDL文档具有契约的描述信息,该文档的结构是XSD。
4.定义服务契约
服务契约的定义仅仅涉及到System.ServiceModel.ServiceContractAttribute和System.ServiceModel.OperationContractAttribute
这两个自定义特性的应用
ServiceContractAttribute
pubulic sealed class ServiceContractAttribute : Attribute { //其他成员 //契约的名称,默认名称接口或类的名称 public string Name{get;set;} //命名空间,默认http://tempuri.org/,建议采用公司名称或项目名称作为命名空间 public string Namespace{ get; set;} //终结点配置项的contract属性,默认命名空间.接口或类名称 public string ConfigurationName{get; set; } //在双工通信实现的回调中,指定用于定义回调操作的接口或类型 public Type CallbackContract{get; set;} public ProtectionLevel ProtectionLevel{get; set; } //消息保护级别 public bool HasProtectionLevel{ get;} //服务采用何种会话模式,枚举类型Allowed、Required、NotAllowed public SessionMode SessionMode{get; set;} }
OperationContractAttribute
[AttributeUsage(AttributeTargets.Method)] pubilc sealed class OperationContractAttribute:Attribute { //其他成员 //服务操作名称,默认方法名称,注:不允许多个操作共享同一名称,同时契约中的每个方法签名必须不同 public string Name {get; set; } //控制基于某个操作的请求消息<Action>报头,默认值:http://{服务契约命名空间}/{服务契约名称}/{操作名称} public string Action {get; set;} //控制基于某个操作的回复消息<Action>报头,默认值:http://{服务契约命名空间}/{服务契约名称}/{操作名称}+Response public string ReplyAction {get; set; } //异步模式定义的操作 public bool AsyncPattern{ get; set; } //消息保护级别 public ProtectionLevel ProtectionLevel { get; set; } //是否对消息保护级别进行显示设置 public bool HasProtectionLevel{ get;} public bool IsInitiating { get; set; } public bool IsTerminating { get; set; } //基于目标操作的服务调用采用单向消息交换模式 public bool IsOneWay { get; set; } }
服务契约的继承
[ServiceContract]
interface IFoo
{
[OperationContract]
void F1();
}
[ServiceContract]
interface IBar:IFoo
{
void F2();
}
5.契约的描述
ContractDescription
OperationContract
MessageDescription
5.契约的描述
由地址、绑定和契约三要素构成的终结点通过类型ServiceEndpoint表示,表示终结点契约的是一个System.ServiceModel.Description.ContractDescription类型对象
public class ServiceEndpoint { //其他成员 public EndpointAddress Address{ get; set; } public Binding Binding{ get; set; } public ContractDescription Contract {get; set;} }
ContractDescription
从命名上就可以看出来,ContractDescription用于描述通过ServiceContractAttribute特性定义的服务契约,如下代码片段所示,定义在ServiceContractAttribute特性中的属性都可以在ContractDescription中找到
public class ContractDescription { //其他成员 //契约的名称,默认名称接口或类的名称 public string Name{get;set;} //命名空间,默认http://tempuri.org/,建议采用公司名称或项目名称作为命名空间 public string Namespace{ get; set;} //终结点配置项的contract属性,默认命名空间.接口或类名称 public string ConfigurationName{get; set; } //服务采用何种会话模式,枚举类型Allowed、Required、NotAllowed public SessionMode SessionMode{get; set;} //是否对消息保护级别进行显示设置 public bool HasProtectionLevel{ get;} //消息保护级别 public ProtectionLevel ProtectionLevel { get; set; } //在双工通信实现的回调中,指定用于定义回调操作的接口或类型 public Type CallbackContract{get; set;} //除了上面这些与ServiceContractAttribute同名属性外,还具有3个属性 //被定义成为服务契约的接口/类的类型 public Type ContractType {get; set;} //只读属性包含了所有契约行为的列表 public KeyedByTypeCollection<IContractBehavior> Behavior { get;} //类型为OperationDescription的集合 public OperationDescriptionCollection Operations {get;} }
OperationContract
对于一个表示契约的ContractDescription对象来说,通过OperationContractAttribute特性定义的所有操作包含在通过只读属性Operations表示的集合中,该集合中的元素是一个类型为OperationDescription的对象,如下代码所示,除了Action、ReplyAction和AsyncPattern属性,其他定义在OperationDescriptionAttribute的属性都可以在OperationDescription中找到
public class OperationDescription { //其他属性 //服务操作名称,默认方法名称,注:不允许多个操作共享同一名称,同时契约中的每个方法签名必须不同 public string Name {get; set; } //消息保护级别 public ProtectionLevel ProtectionLevel { get; set; } //是否对消息保护级别进行显示设置 public bool HasProtectionLevel{ get;} public bool IsInitiating { get; set; } public bool IsTerminating { get; set; } //基于目标操作的服务调用采用单向消息交换模式 public bool IsOneWay { get; set; } //具有三个MethodInfo类型的属性 //同步模式操作方法 public MethodInfo SysncMethod { get; set; } //异步模式的两个操作方法 public MethodInfo BeginMethod{ get; set; } public MethodInfo EndMethod { get; set; } //操作所在的契约 public ContractDescription DeclaringContract { get; set;} //一组用于异常处理的错误契约列表 public FaultDescriptionCollection Faults{ get;} //指定在序列化过程中所需的已知类型 public Collection<Type> KnownTypes {get;} // 包含该操作具有的所有操作行为(包括以特性方式应用在契约操作方法上的行为,也包括在服务操作方法上的行为) public KeyedByTypeCollection<IOperationBehavior> Behavior {get;} // public MessageDescriptionColleciton Message { get;} }
MessageDescription
参与操作消息交换的请求消息和回复消息的描述通过具有如下定义的MessageDescription类型类表示,MessageDescription不仅可以表示消息报头(soap报头)和消息主体结构,还可以表示对整个消息或者针对消息的某个部分采用保护级别等信息。
public class MessageDescription { //其他成员 //枚举:Input Output代表代表消息是作为输入(请求)还是输出(回复) public MessageDirection Direction{ get; } //控制基于某个操作的请求消息<Action>报头,默认值:http://{服务契约命名空间}/{服务契约名称}/{操作名称} public string Action {get ;} //SOAP消息报头列 public MessageHeaderDescriptionCollection Headers { get;} //SOAP消息主体 public MessageBodyDescription Body { get ;} //消息保护级别 public ProtectionLevel protectionleve {get; set;} //是否对消息保护级别进行显示设置 public bool HasProtectionLevel{ get;} //返回是操作的输入/输出使用的消息契约的类型,非消息契约返回Null public Type MessageType{get; set;} // public MessagePropertyDescriptionCollection Properties{ get;} }
还有一对象MessagePartDescription用于描述消息的某个“部分”
public class MessagePartDescription { public string Name {get;} public string Namespace{ get;} //用于保护消息所采用的签名/加密 不仅可以针对整个消息,还可以专门针对消息的某个部分 public ProtectionLevel ProtectionLevel { get; set;} public bool HasProtectionLevel {get;} //Index Multiple分表表示MessagePartDescription在消息中的位次,以及表明它是否可以出现多次 public int Index { get; set;} public bool Multiple { get; set;} //如果MessagePartDescription用于描述消息契约的某根部分,则MemberInfo和Type属性分别返回对应属性/字段的 //MemberInfo和类型 public MemberInfo MemberInfo {get; set;} public Type Type {get; set;} }
MessageHeaderDescription用于描述单个消息报头
public class MessageHeaderDescription :MessagePartDescription { //其他成员 其中Actor MustUnderstand和Replay都是标准的SOAP报头属性 //Actor表示目标接收方 public string Actor {get; set;} //表示消息报头是否必须能够被接收方理解并处理 public bool MustUnderstand{ get; set;} //表示如果报头没有被处理是否应该被转发 public bool Replay { get; set;} //如果以消息契约的方式将某个类型的属性/字段定义成消息报头,那么TypedHeader 返回True public bool TypedHeader{get; set;} }
MessageBodyDescription用于描述消息主体部分
public class MessageBodyDescription { //其他成员 //parts和returnVlaue分别表示基于参数列表的messagePartsDescription列表和表示返回值的MessagepartDescription public MessagePartDescriptionCollection Parts{get;} public MessagePartDescription ReturnValue { get; set;} //WrapperName和WrapperNamespace用于封装整个消息主体部分的XML元素的名称和命名空间 public string WrapperName {get; set;} public string WrapperNamespace { get; set;} }
此篇主要是围绕着契约中的各个对象介绍,有个大体了解