任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源。同理,一个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: public class ServiceDescription
   2: {
   3:     //其他成员
   4:     public KeyedByTypeCollection<IServiceBehavior> Behaviors { get; }
   5:     public string ConfigurationName { get; set; }
   6:     public ServiceEndpointCollection Endpoints { get; }
   7:     public string Name { get; set; }
   8:     public string Namespace { get; set; }
   9:     public Type ServiceType { get; set; }
  10: }

1、Name与Namespace

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

   1: [ServiceBehavior] 
   2: public class CalculatorService : ICalculator 
   3: { 
   4:     //省略成员 
   5: } 

   1: [ServiceBehavior(Name = "CalculatorService", Namespace = "http://tempuri.org/")]
   2: public class CalculatorService : ICalculator
   3: {
   4:     //省略成员
   5: }

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

   1: [ServiceBehavior(Name = "CalcService", Namespace = "http://www.artech.com/")]
   2: public class CalculatorService : ICalculator
   3: {
   4:     //省略成员
   5: }

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <wsdl:definitions name="CalcService" targetNamespace= http://www.artech.com/ 
   3: ...>
   4:     ......
   5:     <wsdl:service name="CalcService">
   6:         ......
   7:     </wsdl:service>
   8: </wsdl:definitions>

2、ConfigurationName

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

   1: namespace Artech.ServiceDescriptionDemos
   2: {    
   3:     [ServiceBehavior]
   4:     public class CalculatorService : ICalculator
   5:     {
   6:         //省略成员
   7:     }
   8: }

   1: namespace Artech.ServiceDescriptionDemos
   2: {    
   3:     [ServiceBehavior(ConfigurationName = "Artech.ServiceDescriptionDemos.CalculatorService")]
   4:     public class CalculatorService : ICalculator
   5:     {
   6:         //省略成员
   7:     }
   8: }

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

   1: namespace Artech.ServiceDescriptionDemos
   2: {    
   3:     [ServiceBehavior(ConfigurationName = "CalculatorService")]
   4:     public class CalculatorService : ICalculator
   5:     {
   6:      //省略成员
   7:     }
   8: }

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <system.serviceModel>        
   4:         <services>
   5:             <service name="CalculatorService">
   6:                 ......
   7:             </service>
   8:         </services>
   9:     </system.serviceModel>
  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: public interface IServiceBehavior
   2: {
   3:     void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters);
   4:     void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase);
   5: void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase);
   6: }

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

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //省略成员
   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: public class ServiceEndpoint
   2: {
   3:     //其他成员
   4:     public EndpointAddress Address { get; set; }
   5:     public KeyedByTypeCollection<IEndpointBehavior> Behaviors { get; }
   6:     public Binding Binding { get; set; }
   7:     public ContractDescription Contract { get; }
   8:     public Uri ListenUri { get; set; }
   9:     public ListenUriMode ListenUriMode { get; set; }
  10:     public string Name { get; set; }
  11: }

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

   1: public interface IEndpointBehavior
   2: {
   3:     void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);
   4:     void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);
   5:     void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher);
   6: void Validate(ServiceEndpoint endpoint);
   7: }

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

三、ContractDescription和ContractBehavior

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

   1: public class ContractDescription
   2: {
   3:     //其他成员
   4:     public KeyedByTypeCollection<IContractBehavior> Behaviors { get; }
   5:     public OperationDescriptionCollection Operations { get; }
   6: }

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

   1: public interface IContractBehavior
   2: {
   3:     void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);
   4:     void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime);
   5:     void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime);
   6: void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint);
   7: }

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

四、 OperationDescription和OperationBehavior

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

   1: public class OperationDescription
   2: {
   3:     //其他成员
   4:     public KeyedByTypeCollection<IOperationBehavior> Behaviors { get; }    
   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: public interface IOperationBehavior
   2: {
   3:     void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters);
   4:     void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation);
   5:     void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation);
   6: void Validate(OperationDescription operationDescription);
   7: }

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

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

    任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源.同理,一个WCF服务的监听与执行同样需要通过一个进程来承载.我们将为WCF服务创建或指定一个进程的方式称为服务 ...

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

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

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

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

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

    元数据实际上是服务终结点的描述,终结点由地址(Address).绑定(Binding)和契约(Contract)经典的ABC三要素组成.认真阅读过<WCF技术剖析(卷1)>的读者相对会对这 ...

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

    元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框架体系中,元数据的导出工作由MetadataExporter实现.MetadataExp ...

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

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

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

    通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultException异常),其相关的错误信息仅仅限于服务端可见,并不会被WC ...

  8. WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[上篇](转)...

    http://www.cnblogs.com/artech/archive/2009/11/05/1596925.html 服务调用的目的体现在对某项服务功能的消费上,而功能的实现又定义在相应的服务类 ...

  9. WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[中篇]

    在[第1篇]中,我们介绍了WCF关于实例管理一些基本的知识点,包括InstanceContext.InstanceContextMode.已经如何通过ServiceBehaviorAttribute应 ...

最新文章

  1. 生成式对抗网络GAN有哪些最新的发展,可以实际应用到哪些场景中
  2. Maven下载、安装和配置(转)
  3. css3+jQuery制作导航菜单(带动画效果)
  4. 六周第四次课(1月18日)
  5. 25、HTML 文本格式化
  6. Java 7 中 NIO.2 的使用——第四节 文件和目录
  7. Java笔记04-核心类库
  8. 国外程序员访谈:学无止境
  9. 转载:ASP.net页面跳转方式三种
  10. adobe出的cookbook
  11. Python安装包下载方式
  12. 开源库uthash第一弹uthash.h
  13. JAVA前后端分离项目脚手架
  14. MySQL主从配置(Django实现主从配置读写分离)
  15. 动态规划处理长方形分割为正方形问题
  16. 哈工大计算机科学与技术邬向前,人工智能学院组队赴哈工大交流学习
  17. 关于error in opening zip file
  18. 微软邮箱(@outlook.com/@hotmail.com):双重验证+应用密码
  19. 前端如何学习,学习以后干什么?
  20. 实现微信公众号二维码生成

热门文章

  1. 道闸系统临时服务器什么意思,停车场管理系统常见问题解答
  2. 通过 WSL在Windows下愉快的玩耍Linux
  3. 自己定义ViewGroup实现仿淘宝的商品详情页
  4. Vue 3D轮播插件vue-carousel-3d
  5. 星象仪- 大塚爱 歌词
  6. POI设置Excel单元格样式和背景色
  7. styled 手撸Switch开关
  8. Linux NFS网络文件系统
  9. 在这家不加班的 IT 公司里,我们是这样加班的
  10. 四十三、迎接挑战,苦练内功,迎接春天的到来