1.3.4 步骤四 通过自我寄宿的方式寄宿服务
WCF服务须要依存一个运行着的进程(宿主),服务寄宿就是为服务指定一个宿主的过程。WCF是一个基于消息的通信框架,采用基于终结点(Endpoint)的通信手段。终结点由地址(Address)、绑定(Binding)和契约(Contract)三要素组成,如图1-4所示。由于三要素的首字母分别为A、B、C,所以就有了易于记忆的公式:Endpoint = ABC。一个终结点包含了实现通信所必需的所有信息,我们可以这样认识终结点的ABC:
图1-4 终结点三要素
● 地址(Address):地址决定了服务的位置,解决了服务寻址的问题,第2章提供了对地址和寻址机制的详细介绍。
● 绑定(Binding):绑定实现了通信的所有细节,包括网络传输、消息编码,以及其他为实现某种功能(比如安全、可靠传输、事务等)对消息进行的相应处理。WCF中具有一系列的系统定义绑定,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,第3章提供对绑定的详细介绍。
● 契约(Contract):契约是对服务操作的抽象,也是对消息交换模式及消息结构的定义。第4章提供对服务契约的详细介绍。
服务寄宿的目的就是开启一个进程,为WCF服务提供一个运行的环境。通过为服务添加一个或多个终结点,使之暴露给潜在的服务消费者。服务消费者最终通过相匹配的终结点对该服务进行调用。我们完全可以通过代码的方式完成所有的服务寄宿工作,下面的代码体现了通过一个控制台应用对CalculatorService的寄宿:
using System; using System.ServiceModel; using System.ServiceModel.Description; using Artech.WcfServices.Contracts; using Artech.WcfServices.Services; namespace Artech.WcfServices.Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof (CalculatorService))) { host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(),"http://127.0.0.1:9999/calculatorservice"); if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://127.0.0.1:9999/ calculatorservice/metadata"); host.Description.Behaviors.Add(behavior); } host.Opened += delegate { Console.WriteLine("CalculaorService已经启动,按任意键终止服务!"); }; host.Open(); Console.Read(); } } } }
WCF服务寄宿通过一个特殊的对象完成:ServiceHost。在上面的例子中,基于WCF服务的类型(typeof(CalculatorService))创建了ServiceHost对象,并添加了一个终结点。具体地址为http://127.0.0.1:9999/calculatorservice,采用WsHttpBinding,并指定了服务契约的类型ICalculator。
松耦合是SOA的一个基本的特征,WCF应用中客户端和服务端的松耦合体现在客户端只须要了解WCF服务基本的描述,而无须知道具体的实现细节,就可以实现正常的服务调用。WCF服务的描述通过元数据(Metadata)的形式发布出来。WCF中元数据的发布通过一个特殊的服务行为ServiceMetadataBehavior来实现。在上面提供的服务寄宿代码中,我们为创建的ServiceHost添加了ServiceMetadataBehavior,并采用了基于HTTP-GET的元数据获取方式,元数据的发布地址通过ServiceMetadataBehavior的HttpGetUrl指定。在调用ServiceHost的Open方法对服务成功寄宿后,我们可以通过该地址获取服务相关的元数据。在IE地址栏上键入http://127.0.0.1:9999/calculatorservice/metadata,你将会得到以WSDL形式体现的服务元数据,如图1-5所示。
图1-5 通过HTTP-GET的方式获取WCF服务的元数据
在进行真正的WCF应用开发时,一般不会直接通过编码的方式进行终结点的添加和服务行为的定义,而是通过配置的方式进行。上面添加终结点和定义服务行为的代码可以用下面的配置代替:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="metadataBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl= "http://127.0.0.1:9999/calculatorservice/metadata" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="metadataBehavior" name= "Artech.WcfServices.Services.CalculatorService"> <endpoint address="http://127.0.0.1:9999/calculatorservice" binding="wsHttpBinding" contract="Artech.WcfServices. Contracts.ICalculator" /> </service> </services> </system.serviceModel> </configuration>
对于初学者来说,WCF的配置显得过于复杂,直接对配置文件进行手工编辑不太现实。在这种情况下,可以直接使用VS提供的配置工具。你可以通过VS的工具(Tools)菜单,选择“WCF Service Configuration Editor”子项,开启这样的一个配置编辑器,如图1-6所示。
图1-6 如何获得WCF服务配置编辑器
如果采用了上述的配置,服务寄宿代码将会得到极大的精简,只须包含下面几行代码:
namespace Artech.WcfServices.Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(CalculatorService))) { host.Opened += delegate { Console.WriteLine("CalculaorService已经启动,按任意键终止服务!"); }; host.Open(); Console.Read(); } } } }