原文:WCF技术剖析之二十: 服务在WCF体系中是如何被描述的?

任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源。同理,一个WCF服务的监听与执行同样需要通过一个进程来承载。我们将为WCF服务创建或指定一个进程的方式称为服务寄宿(Service Hosting)。服务寄宿的本质通过某种方式,创建或者指定一个进程用以监听服务的请求和执行服务操作,为服务提供一个运行环境。

服务寄宿的方式大体分两种:一种是为一组WCF服务创建一个托管的应用程序,通过手工启动程序的方式对服务进行寄宿,所有的托管的应用程序均可作为WCF服务的宿主,比如Console应用、Windows Forms应用和ASP.NET应用等,我们把这种方式的服务寄宿方式称为自我寄宿(Self Hosting)。另一种则是通过操作系统现有的进程激活方式为WCF服务提过宿主,Windows下的进程激活手段包括IIS、Windows Service或者WAS(Windows Process Activation Service)等。

服务寄宿的手段是为一个WCF服务类型创建一个ServiceHost对象(或者任何继承于ServiceHostBase的对象)。无论采用哪种寄宿方式,在为某个服务创建ServiceHost的过程中,WCF框架内部会执行一系列的操作,其中最重要的步骤就是为服务创建服务描述(Service Description)。在本篇文章中,我们将对服务描述进行全面的介绍。

WCF服务描述通过类型System.ServiceModel.Description.ServiceDescription表示,ServiceDescription对象是WCF服务运行时的描述。除了包含WCF服务的一些基本信息,比如服务的名称、命名空间和CLR类型等,ServiceDescription还包含服务所有终结点和服务行为的描述。

一、 ServiceDescription与ServiceBehavior

从下面ServiceDescription的定义可以看出,ServiceDescription中定义了一系列属性,它们的含义如下:

  • Behaviors服务行为(Service Behavior)的集合
  • ConfigurationName:服务的在配置文件中的名称,默认为服务类型的全名(命名空间+类型名称)
  • Name服务的名称,默认为服务类型名称(不包含命名空间)
  • Namespace服务的命名空间,默认为“http://tempuri.org/”
  • ServiceType服务的CLR类型
  1. 1: public class ServiceDescription

  1. 2: {

  1. 3: //其他成员

  1. 4: public KeyedByTypeCollection<IServiceBehavior> Behaviors { get; }

  1. 5: public string ConfigurationName { get; set; }

  1. 6: public ServiceEndpointCollection Endpoints { get; }

  1. 7: public string Name { get; set; }

  1. 8: public string Namespace { get; set; }

  1. 9: public Type ServiceType { get; set; }

  1. 10: }

1、Name与Namespace

ServiceDescription的NameNamespace分别表示服务的名称和命名空间,这两个属性同样体现在服务发布的WSDL中。可以通过System.ServiceModel.ServiceBehaviorAttributeNameNamespace属性进行设定。ServiceDescription的Name和Namespace的默认值分别为服务类型名称和http://tempuri.org/,所以下面两种定义是等效的。

  1. 1: [ServiceBehavior]

  1. 2: public class CalculatorService : ICalculator

  1. 3: {

  1. 4: //省略成员

  1. 5: }

  1. 1: [ServiceBehavior(Name = "CalculatorService", Namespace = "http://tempuri.org/")]

  1. 2: public class CalculatorService : ICalculator

  1. 3: {

  1. 4: //省略成员

  1. 5: }

而ServiceDescription的Namespace映射WSDL的目标命名空间(targetNamespace),Name则直接对应<wsdl:service>节点的Name属性。在下面的服务定义中,通过ServiceBehaviorAttribute将Name和Namespace设置为“CalcService”和“http://www.artech.com/”,后面的XML体现了服务在WSDL表示。

  1. 1: [ServiceBehavior(Name = "CalcService", Namespace = "http://www.artech.com/")]

  1. 2: public class CalculatorService : ICalculator

  1. 3: {

  1. 4: //省略成员

  1. 5: }

  1. 1: <?xml version="1.0" encoding="utf-8"?>

  1. 2: <wsdl:definitions name="CalcService" targetNamespace= http://www.artech.com/

  1. 3: ...>

  1. 4: ......

  1. 5: <wsdl:service name="CalcService">

  1. 6: ......

  1. 7: </wsdl:service>

  1. 8: </wsdl:definitions>

2、ConfigurationName

ServiceDescription的ConfiguraitonName表示服务的配置名称,可以同样可以通过System.ServiceModel.ServiceBehaviorAttribute的同名属性进行设定。在默认情况下,ConfiguraitonName的值为服务类型的全名(命名空间+类型名称),下面两种服务的定义是等效的。

  1. 1: namespace Artech.ServiceDescriptionDemos

  1. 2: {

  1. 3: [ServiceBehavior]

  1. 4: public class CalculatorService : ICalculator

  1. 5: {

  1. 6: //省略成员

  1. 7: }

  1. 8: }

  1. 1: namespace Artech.ServiceDescriptionDemos

  1. 2: {

  1. 3: [ServiceBehavior(ConfigurationName = "Artech.ServiceDescriptionDemos.CalculatorService")]

  1. 4: public class CalculatorService : ICalculator

  1. 5: {

  1. 6: //省略成员

  1. 7: }

  1. 8: }

如果配置文件中<service>的Name属性更改了,在服务定义中需要通过ServiceBehaviorAttribute对ConfigurationName进行相应的修正,如下面的代码所示。

  1. 1: namespace Artech.ServiceDescriptionDemos

  1. 2: {

  1. 3: [ServiceBehavior(ConfigurationName = "CalculatorService")]

  1. 4: public class CalculatorService : ICalculator

  1. 5: {

  1. 6: //省略成员

  1. 7: }

  1. 8: }

  1. 1: <?xml version="1.0" encoding="utf-8" ?>

  1. 2: <configuration>

  1. 3: <system.serviceModel>

  1. 4: <services>

  1. 5: <service name="CalculatorService">

  1. 6: ......

  1. 7: </service>

  1. 8: </services>

  1. 9: </system.serviceModel>

  1. 10: </configuration>

3、服务行为(Service Behavior)

如果说契约(Contract)是涉及双边的描述(契约是服务的提供者和服务消费者进行交互的依据),那么行为(Behavior)就是基于单边的描述。客户端行为体现的是WCF如何进行服务调用的方式,而服务端行为则体现了WCF的请求分发方式。行为是对WCF进行扩展的最为重要的方式,按照行为作用域的不同,WCF的行为大体包含以下四种:

  • 服务行为(Service Behavior):基于服务本身的行为,实现了接口System.ServiceModel.Description.IServiceBehavior,可以通过Attribute或者配置的方式进行指定
  • 终结点行为(Endpoint Behavior):基于某个服务终结点(客户端或者服务端)的行为,实现了接口System.ServiceModel.Description.IEndpointBehavior,可以通过配置的方式进行指定
  • 契约行为(Contract Behavior):基于某个服务契约的行为,作用于实现了该契约的所有服务(服务端行为)和基于该契约进行服务调用的服务代理(客户端行为),实现了接口System.ServiceModel.Description.IContractBehavior,可以通过Attribute的方式进行指定
  • 操作行为(Operation Behavior):基于服务契约中的某个操作契约,作用于实现了该服务契约的服务对应的服务操作(DispatchOperation)和基于该操作契约进行服务调用的客户操作(ClientOperation),实现了接口System.ServiceModel.Description.IOperationBehavior,可以通过Attribute进行指定

在ServiceDescription中,类型为KeyedByTypeCollection<IServiceBehavior>的Behaviors属性表示服务所有的服务行为集合。所有的服务行为都实现了System.ServiceModel.Description.IServiceBehavior接口。IServiceBehavior定义如下,从中可以看出IServiceBehavior定义了如下三个方法。

注:KeyedByTypeCollection<T>可以看成是以T实例为Value,Value对象真实类型为Key的Dictionary,可以通过类型定位并获取相应的成员对象。

  • AddBindingParameters为某个自定义绑定元素(Custom Binding Element)添加绑定参数,以指导或者确保绑定元素的正常操作,比如通过设置的绑定参数创建相应的信道
  • ApplyDispatchBehavior通过改变WCF服务端分发系统的属性,或者添加/替换分发系统中用以实现某种分发操作的可扩展对象,进而改变服务分发的行为
  • Validate:通过检验服务描述,用以保证后续工作的正常执行
  1. 1: public interface IServiceBehavior

  1. 2: {

  1. 3: void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters);

  1. 4: void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase);

  1. 5: void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase);

  1. 6: }

WCF为我们预定义了一系列的ServiceBehavior,其中ServiceBehaviorAttribute就是其中之一。ServiceBehaviorAttribute不仅仅是一个自定义特性(Custom Attribute),实际上它本身就是一个实现了IServiceBehavior的服务行为。

  1. 1: [AttributeUsage(AttributeTargets.Class)]

  1. 2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior

  1. 3: {

  1. 4: //省略成员

  1. 5: }

对于其他一些预定义服务行为,比如用于实现与ASP.NET兼容的AspNetCompatibilityRequirementsAttribute;用于进行限流控制的ServiceThrottlingBehavior;用于进行服务授权的ServiceAuthorizationBehavior等,可以通过配置的方式应用于某个WCF服务。

对于ServiceDescription来说,最重要的要数System.ServiceModel.Description.ServiceEndpointCollection类型的Endpoints属性。该属性表示为服务添加的所有在终结点集合,集合的每个元素为System.ServiceModel.Description.ServiceEndpoint对象,接下来我们就来着重讨论ServiceEndpoint。

二、 ServiceEndpoint与EndpointBehavior

ServiceEndpoint对象是对终结点的运行时描述,终结点的三要素(ABC:Address、Binding、Contract)分别由同名的属性表示。ListenUri和ListenUriMode表示终结点真正的监听地址和监听模式,Address和ListenUri由被称为逻辑地址和物理地址(关于逻辑地址和物理地址,可以参考[原创]WCF后续之旅(15): 逻辑地址和物理地址)。

  1. 1: public class ServiceEndpoint

  1. 2: {

  1. 3: //其他成员

  1. 4: public EndpointAddress Address { get; set; }

  1. 5: public KeyedByTypeCollection<IEndpointBehavior> Behaviors { get; }

  1. 6: public Binding Binding { get; set; }

  1. 7: public ContractDescription Contract { get; }

  1. 8: public Uri ListenUri { get; set; }

  1. 9: public ListenUriMode ListenUriMode { get; set; }

  1. 10: public string Name { get; set; }

  1. 11: }

在ServiceEndpoint中,类型为KeyedByTypeCollection<IEndpointBehavior>的Behaviors属性表示绑定到该终结点的终结点行为(Endpoint Behavior)集合。集合的成员为实现了IEndpointBehavior接口的终结点行为对象。IEndpointBehavior的定义如下,AddBindingParameters、ApplyDispatchBehavior和Validate与IServiceBehavior同名方法语义类似。不同的是,IEndpointBehavior的所有方法的作用域仅限于当前终结点,并且IEndpointBehavior既可以作用于服务端,也可以用于客户端。为此,增加了一个新的方法:ApplyClientBehavior。ApplyClientBehavior方法与ApplyDispatchBehavior相对,通过修改客户端运行时(Client Runtime)的属性,或者添加/替换客户端运行时某些可扩展对象,进而实现控制客户端行为的目的。

  1. 1: public interface IEndpointBehavior

  1. 2: {

  1. 3: void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);

  1. 4: void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);

  1. 5: void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher);

  1. 6: void Validate(ServiceEndpoint endpoint);

  1. 7: }

终结点的契约通过ContractDescription对象表示,为了让大家对服务描述有一个系统的认识,接下来我们继续介绍ContractDescription。

三、ContractDescription和ContractBehavior

System.ServiceModel.Description.ContractDescription定义了以下一些属性用于描述服务契约。由于服务契约通过System.ServiceModel.ServiceContractAttribute定义,所以大部分的属性都和ServiceContractAttribute的属性相匹配,在这里就不再作重复的介绍了。

  1. 1: public class ContractDescription

  1. 2: {

  1. 3: //其他成员

  1. 4: public KeyedByTypeCollection<IContractBehavior> Behaviors { get; }

  1. 5: public OperationDescriptionCollection Operations { get; }

  1. 6: }

在ContractDescription中,类型为KeyedByTypeCollection<IContractBehavior>的属性Behaviors代表基于服务契约的契约行为(Contract Behavior)集合,集合成员为实现了接口IContractBehavior的契约行为对象。IContractBehavior具有与IEndpointBehavior一样的方法成员,但是契约行为作用于实现了该服务契约的所有服务(服务端行为),基于使用该服务契约进行服务调用的服务代理(客户端行为)。

  1. 1: public interface IContractBehavior

  1. 2: {

  1. 3: void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);

  1. 4: void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime);

  1. 5: void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime);

  1. 6: void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint);

  1. 7: }

ContractDescription的Operations属性表示服务契约的所有操作的描述,类型为OperationDescriptionCollection,表示一个OperationDescription对象的集合。接下来,我们来介绍OperationDescription。

四、 OperationDescription和OperationBehavior

System.ServiceModel.Description.OperationDescription定义了一系列的属性用以描述定义在服务契约中操作契约。由于操作契约通过System.ServiceModel.OperationContractAttribute定义,所以OperationDescription的大部分属性与OperationContractAttribute属性一一匹配,在这里就不再作重复的介绍了。

  1. 1: public class OperationDescription

  1. 2: {

  1. 3: //其他成员

  1. 4: public KeyedByTypeCollection<IOperationBehavior> Behaviors { get; }

  1. 5: }

上面我不止一次地提出客户端操作(Client Operation)和服务端操作(Dispatch Operation)的概念,这是由于在运行时,基于相同的OperationDescription创建操作对象在客户端和服务端是不同的,服务端操作称为分发操作(DispatchOperation),通过类型System.ServiceModel.Dispatcher.DispatchOperation 表示,客户端操作通过类型System.ServiceModel.Dispatcher.ClientOperation 表示。

在OperationDescription中,类型为KeyedByTypeCollection<IOperationBehavior>的Behaviors属性表示基于操作的所有操作行为(Operation Behavior)集合,集合成员为实现了IOperationBehavior接口的类型对象。IOperationBehavior具有与IEndpointBehavior、IContractBehavior一样的方法成员。IOperationBehavior的作用域仅限于当前的操作(客户端操作或者服务端操作)。

  1. 1: public interface IOperationBehavior

  1. 2: {

  1. 3: void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters);

  1. 4: void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation);

  1. 5: void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation);

  1. 6: void Validate(OperationDescription operationDescription);

  1. 7: }

作者:Artech
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

WCF技术剖析之二十: 服务在WCF体系中是如何被描述的?的更多相关文章

  1. WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

    原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...

  2. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]

    原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...

  3. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇] 通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding ...

  4. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...

  5. WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇]

    原文:WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇] 在[WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy.WS-Tra ...

  6. WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的?

    原文:WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的? 服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户 ...

  7. WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]

    原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...

  8. WCF技术剖析之二十一: WCF基本的异常处理模式[上篇]

    原文:WCF技术剖析之二十一: WCF基本的异常处理模式[上篇] 由于WCF采用.NET托管语言(C#和NET)作为其主要的编程语言,注定以了基于WCF的编程方式不可能很复杂.同时,WCF设计的一个目 ...

  9. WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)

    原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序) 基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似,但是ServiceMetad ...

随机推荐

  1. Qt 技巧:去除对话框边框 + 设置窗口可移动和透明

    1.去除对话框标题栏和边框 在构造函数里设置:    this->setWindowFlags(Qt::FramelessWindowHint); Qt::Dialog     (按照对话框的形 ...

  2. python 爬一下

    1.安装Requestswindow:pip install requestslinux:sudo pip install requests国内安装缓慢,建议到:http://www.lfd.uci. ...

  3. 设计模式总结4--singleton pattern

    单例模式 保证每个类只有一个实例,并提供一个全局访问点 第一步 构造方法私有化第二步 公有化静态方法获取的实例 懒汉式  public class Bank{ private Bank(){} pri ...

  4. ios7状态栏属性的设置

    /* 状态栏的管理: 1> iOS7之前:UIApplication进行管理 2> iOS7开始:交给对应的控制器去管理 */ // 设置状态栏的样式 - (UIStatusBarStyl ...

  5. 【充电器】小米手机2S电池座充——小米手机官网

    ligh@local-host$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.3 [充电器]小米手机2S电池座充--小米手机官网 小米手机2S电池座 ...

  6. android 仿小米icon处理,加阴影和边框

    本人自己在做一个launcher,所以须要处理icon,加阴影和边框等.这仅仅是一种处理方法,其它的处理方法类似. 源码: https://github.com/com314159/LauncherI ...

  7. UVA 270 Lining Up 共线点 暴力

    题意:给出几个点的位置,问一条直线最多能连过几个点. 只要枚举每两个点组成的直线,然后找直线上的点数,更新最大值即可. 我这样做过于暴力,2.7s让人心惊肉跳...应该还能继续剪枝的,同一直线找过之后 ...

  8. 【转】Android数字证书

    Android数字证书的作用是非常重要的.Android操作系统每一个应用程序的安装都需要经过这一数字证书的签名. Android手机操作系统作为一款比较流行的开源系统在手机领域占据着举足轻重的地位. ...

  9. 写了交互给后台后来不能用?bug多多多又找不到文件效率低?工作流程帮你优化起来~~~~

    前端工作流程(多方交互篇) 新的网页: 1.跟美工沟通,跟产品沟通,跟后台沟通.前两者主要是页面样式.后者主要是表单交互.用哪个框架之类的. 2.实现.(写清楚哪块是用什么验证方式的)→ 给后台. 3 ...

  10. POJ 1155 - TELE 树型DP(泛化背包转移)..

    dp[x][y]代表以x为根的子树..连接了y个终端用户(叶子)..所能获得的最大收益... dp[x][ ]可以看成当根为x时..有个背包空间为0~m...每个空间上记录了到到达这个空间的最大收益. ...