《WCF服务编程》学习笔记

 

第一章 WCF基础

什么是WPF

WCF是基于Windows平台下开发和部署服务的SDK,为服务提供了运行时环境,使得开发者能够将CLR类型公开为服务,又能够以CLR类型的方式使用服务

服务

服务是公开的一组功能的集合

SOA(Service-oriented applications):面向服务应用程序

面向服务的应用程序(SOA)将众多服务聚集到一个单一逻辑的应用程序中,这就类似于面向组件的应用程序聚合组件,或者面向对象的应用程序聚合对象,如图:

《WCF服务编程》学习笔记_第1张图片

服务之间的交互,只允许指定的通信模式

客户端与服务端通过消息的发送与接收进行交互,WCF中的所有消息均为SOAP(Simple Object Access Protocol)消息

WCF服务可以在不同的协议之间传输,而不仅限于HTTP

服务的执行边界

WCF不允许客户端直接与服务交互,即使它调用的是本地机器内存中的服务。相反,客户端总是使用代理(proxy)将调用转发给服务。代理公开的操作与服务相同

使用proxy可以将客户端与服务端的调用地址做解耦

WCF与位置透明度

不管是远程还是本地调用WCF,都统一使用代理的形式,这样统一一种规则可以避免不同方式调用产生的各种问题

地址

WCF的每一个服务都具有一个唯一的地址(Address)。地址包含两个重要元素:服务位置与传输协议(transport protocol),或者是用于服务通信的传输样式(transport schema)

WCF支持下列传输样式:HTTP、TCP、Peer network(对等网)、IPC (内部进程通信) 、MSMQ

地址的格式:

[传输协议]://[机器名或域名][:可选端口]/[可选的URI]

契约

WCF的所有服务都会公开为契约(Contract)。契约与平台无关,是描述服务功能的标准方式

契约的类型有四种:服务契约(ServiceContract)、数据契约、错误契约、消息契约(很少使用)

服务契约例子(定义、实现):

《WCF服务编程》学习笔记_第2张图片

对于没有使用OperationContract特性标识的方法,不会成为契约的一部分

将ServiceContract特性应用在内部(internal)接口上,该接口同样会被公开为公有服务契约。如果接口没有标记ServiceContract特性,WCF客户端则无法访问它(即使接口是公有的)。这一特点遵循了面向服务的一个原则即服务边界应该是明确的。为满足这一原则,所有契约必须明确要求:只有接口(或者类可以被标记为ServiceContract特性,从而被定义为WCF服务,其他类型都不允许

通过应用OperationContract特性,可以将契约方法暴露为逻辑操作,使其成为服务契约的一部分。接口(或类)中的其他方法如果没有应用OperationContract特性,则与契约无关

契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约(所以这里还是有很大灵活空间,引用类型只要你有数据契约就可以作为参数)

当接口应用了ServiceContract特性后,需要定义类实现该接口,定义的实现类的代码无需修改,自然而然成为一个WCF服务(它看起来就是一个普通的类)

WCF只能使用默认构造函数。同样,虽然类可以使用内部(internal)(译注2)[插图]的属性、索引器以及静态成员,但WCF客户端却无法访问它们。

可以直接将ServiceContract特性应用到服务类上(但是,应尽量避免将ServiceContract特性直接应用到服务类上,而应该定义一个单独的契约,这有利于在不同场景下使用契约):

《WCF服务编程》学习笔记_第3张图片

 托管

托管WCF服务的进程是宿主进程,宿主可以由IIS(internet information services)提供

优势是宿主进程可以在客户端提交第一次请求的时候自动启动,缺点则在于只能使用HTTP协议

在IIS中托管服务需要在IIS下创建一个虚拟目录,并提供一个.svc文件,该文件的作用是识别到对应的服务代码:

使用IIS 5/6托管,服务的基地址必须与.svc文件的地址保持一致

自托管

在console程序中使用WCF服务,程序和服务都在一个进程中

简单的建立一个IIS服务,并启动:

《WCF服务编程》学习笔记_第4张图片

可以使用ServiceHost中的一些委托,来输出一些日志,以说明服务的生命周期阶段

绑定

WCF引入绑定(Binding)技术是为了将繁杂的通信特征组合在一起,实现统一管理

一个绑定封装了诸如传输协议、消息编码、通信模式、可靠性、安全性、事务传播以及互操作性等相关选项的集合,使得它们保持一致

绑定将所有繁杂的基础功能模块从服务代码中解放出来,允许服务只需要关注业务逻辑的实现

绑定使得开发者能够基于不同的基础功能模块使用相同的服务逻辑

使用哪种绑定可以参考如下:

《WCF服务编程》学习笔记_第5张图片

终结点

地址定义了服务的位置,绑定定义了服务通信的方式,契约则定义了服务的内容

终结点就是地址、契约与绑定的混成品。每一个终结点都包含了三个元素,而宿主则负责公开终结点,从逻辑上讲,终结点相当于服务的接口

每个服务至少必须公开一个业务终结点,每个终结点有且只能拥有一个契约。服务上的所有终结点都包含了唯一的地址,而一个单独的服务则可以公开多个终结点。这些终结点可以使用相同或不同的绑定,公开相同或不同的契约

使用配置文件的方式配置终结点:

《WCF服务编程》学习笔记_第6张图片

编程方式配置终结点:

《WCF服务编程》学习笔记_第7张图片

元数据交换

服务有两种方案可以发布自己的元数据。一种是基于HTTP-GET协议提供元数据

WCF能够为服务自动提供基于HTTP-GET的元数据,但需要显式地添加服务行为(Behavior)以支持这一功能,如下:

《WCF服务编程》学习笔记_第8张图片

这样设置之后,我们可以使用HTTP访问:

《WCF服务编程》学习笔记_第9张图片

编程方式启用元数据:

《WCF服务编程》学习笔记_第10张图片

客户端编程

客户端使用了WCF,调用操作的常见做法是使用代理

生成代理

①直接在vs ide上生成代理:

《WCF服务编程》学习笔记_第11张图片

之后直接输入服务地址即可

②使用SvcUtil(SvcUtil.exe是.net自带的工具)

指令:SvcUtil 服务地址 指令选项

以上两种方式都会生成两个文件:一个是客户端需要的配置文件(建议不自动生成配置文件,而是手动配置管理),一个就是代理类

管理方式配置客户端

《WCF服务编程》学习笔记_第12张图片

客户端的终结点配置基本与宿主相同

进程内托管配置服务端和客户端的配置在一个配置文件中

SvcConfigEditor编辑器

右键App.config使用Edit WCF Configuration,可快捷编辑配置文件

创建和使用代理

ClientBase类通过泛型类型参数识别代理封装的服务契约。ClientBase的Channel属性类型就是泛型参数的类型。生成的ClientBase的子类仅仅是将方法调用委托给Channel。调用Channel属性的方法会将适当的WCF消息发送给服务

使用代理例子:

《WCF服务编程》学习笔记_第13张图片

如果一个契约在配置文件中只包含一个终结点,那么在初始化客户端实例的时候不需要传入具体的Endpoint信息,如果一个契约在配置文件中包含多个终结点,那么在初始化客户端实例的时候需要传入具体的Endpoint信息

如果类继承了IDisposable接口,可以使用using语法,就不需要手动执行Dispose和Close操作

调用超时

WCF服务端对于客户端默认的超时时间是1min,可以使用配置自定义超时时间

《WCF服务编程》学习笔记_第14张图片

编程方式配置与管理方式配置

管理配置方式允许开发者在部署服务之后,修改服务与客户端的主要特性,而不需要重新编译或重新部署。主要缺陷则是不具备类型安全,只有在运行时才能发现配置的错误

WCF体系架构

《WCF服务编程》学习笔记_第15张图片

使用通道

可以直接使用通道调用服务的操作,而无须借助于代理类:

《WCF服务编程》学习笔记_第16张图片

可靠性

传输可靠性依靠TCP进行点对点传递

消息可靠性提供了端对端保证传递,确保消息的顺序无误

绑定与可靠性

WCF的可靠性在绑定中控制与配置的

配置可靠性

配置方式:

《WCF服务编程》学习笔记_第17张图片

编码方式:

必备有序性

使用DeliveryRequirement特性,该定义可以定义到服务级,也可以定义到契约级

第二章 服务契约

操作重载

《WCF服务编程》学习笔记_第18张图片

在WCF中,这样的重载是不支持的,需要使用OperationContract的Name属性的别名以获取支持

《WCF服务编程》学习笔记_第19张图片

契约的继承

契约之间可以继承,但是ServiceContract特性是不能继承的,所以接口层级中的每级接口都必须显示的标记该特性

服务契约的分解与设计

契约分解

在面向服务的应用程序中,一个可重用的基本单元就是服务契约

契约查询

编程处理元数据

《WCF服务编程》学习笔记_第20张图片

第三章 数据契约

序列化

服务元数据允许客户端将与平台、技术无关的表示形式转换为客户端本地的表示形式

.NET序列化

Serializable特性

如果标记了Serializable特性的类中有不支持序列化的内容,需要给它加上NonSerializable特性:

《WCF服务编程》学习笔记_第21张图片

NonSerialized不局限于标记不可序列化的内容,如果序列化类中有任何内容不需要做序列化都可以加上这个特性

序列化数据契约

为了能够在操作中使用定制类型参数,必须符合两个条件:

  1. 类型必须是可序列化的
  2. 客户端与服务端都拥有该类型的本地定义且该类型应该具有相同的数据样式

数据契约特性

Serializable的弊端:

  1. 不支持类型名和成员名的别名
  2. 破坏了面向对象的封装性
  3. 没有直接支持版本控制

WCF提供的新的面向服务特性:DataContract

DataContract只能够做到将类型参与到数据契约中,如下:

《WCF服务编程》学习笔记_第22张图片

在客户端使用该结构体时,不能够为成员赋值:

《WCF服务编程》学习笔记_第23张图片

如果想要序列化类型的成员,需要使用DataMember特性

《WCF服务编程》学习笔记_第24张图片

在客户端就可以为该结构体下的成员赋值了:

数据契约与Serializable特性:

在服务端的类型虽然标记的是Serializable特性,但是通过对客户端导入元数据,解析该类型时,导入的定义依然会使用DataContract特性:

服务端:

《WCF服务编程》学习笔记_第25张图片

客户端:

《WCF服务编程》学习笔记_第26张图片

从上面可以看到,既有Serializable特性又有DataContract特性,这是因为传统的格式器不能序列化只标记了DataContract特性的类型,必须两个特性同时定义在类型上才可序列化

你可能感兴趣的:(《WCF服务编程》学习笔记)