虽然已经在多个项目中成功应用过WCF,但是感觉自己对WCF的知识只知道一些皮毛而已。上次学习WCF也是为了项目需要,囫囵吞枣。这不是我学习方法的态度。所以时至今日,又重新拾卷,再仔细的将WCF一些细节知识,边边角角自己回顾一番。

 

Host

三种Host的方式:IIS Host、WAS Host、Self-Host。

IIS Host

IIS这种非常简单,但只支持HTTP协议。不过,你可以借助IIS来管理服务的生命周期。在IIS上发布WCF Service是极其简单的,只需要写一个后缀名为svc的文件就ok了:

<%@ ServiceHost Language=”C#” Debug=”false” CodeBehind=”~/App_Code/MyService.cs” Service=”MyService” %>

还记得Web Service的asmx文件么?是不是如出一辙!

Self-Host

顾名思义,就是自托管了。开发人员完全控制,你可以将服务驻留在Console Application、WinForm、Windows Service。只需要保证服务先于客户端启动就Ok了。使用这种托管方式,开发人员可以完全的控制,可以使用任何协议,灵活性最大。

WAS Host

WAS的全称是Windows Activation Service,是个系统服务,跟随Vista发布的,是IIS 7的一部分,但是也可以单独安装和配置。要使用WAS,和IIS Host一样,也需要提供一个svc文件。但是,WAS不仅仅可以使用HTTP,可以使用WCF可以使用的任何协议。

WAS提供了很多Self-Host没有的优点,比如应用程序池、回收、身份管理等。

Endpoint

WCF中最重要的概念莫过于Endpoint了,Endpoint就是服务的接口。一个Endpoint包括三个要素:Address、Binding、Contract。

这三个方面实际上表达的是Where?How?What?的意思。

Address就是我到哪里(Where)寻找这个服务?

Binding就是我如何(How)与这个服务交互?

Contract就是这个服务是什么(What)?

每个Endpoint必须具有三个要素,缺一不可。

ServiceHost

Host架构

【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage

Service就驻留在ServiceHost实例中,每个ServiceHost实例只能托管一个服务。每个ServiceHost可以有多个Endpoint。一个进程里面可以有多个ServiceHost实例,同个宿主进程里不同的ServiceHost实例可以享用相同的BaseAddress。

使用Visual Studio自动生成服务端

Visual Studio的项目模板里已经为我们准备了WCF Service Application,使用Visual Studio创建的WCF Service Application项目默认是使用IIS托管的(WAS的托管方式与IIS的类似):
【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage

生成后的工程(经过修改):
【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage

如果采用Selft-Host该怎么办呢?Visual Studio里还有一个WCF Service Library的项目模板,我们可以使用这个模板为Self-Host生成很多代码:
【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage
添加后生成的工程(经修改):
【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage

但不管是WCF Service Application还是WCF Service Library,我觉得这种自动生成的方式都不太好。从上面几个图我们可以看出,这两种项目模板都将服务契约与服务的实现放在同一个项目中,最后编译出来服务契约与服务实现也在同一个程序集中,既然如此那为何又要将契约和服务分开?不是多次一举么?对于Best Practice来讲,我们应该永远都为每个服务创建一个接口,而将[ServiceContract]特性加在这些接口上,然后在另一个项目里编写服务的实现类,引用服务契约的项目,实现这些接口(契约)。所以无论从学习还是Best Practice来讲,我们都应该具有手动从头到尾编写服务契约、实现服务、服务托管的代码的能力:

代码示例:

//订单项
   2: [DataContract]
class OrderItem
   4: {
   5:     [DataMember]
int Id{get;set;}
   7:     [DataMember]
int ProductId{get;set;}
   9: }
//订单
  11: [DataContract]
class Order
  13: {
  14:     [DataMember]
int OrderId{get;set;}
  16:  
  17:     [DataMember]
public IList<OrderItem> OrderItems{get;set;}
  19: }

相关文章: