本应用的功能虽然简单,但它具有一个完整WCF应用的基本结构。在这个例子中,我们将实现一个简单的计算服务来提供基本的加、减、乘、除运算。客户端和服务通过运行在同一台机器上的不同程序来模拟,下图体现了客户端和服务端进程互相调用的关系。
WCF的服务不能孤立地存在,需要寄宿在一个运行着的进程中,我们把承载WCF服务的进程称为宿主,为服务指定宿主的过程成为服务寄宿(Service Hosting)。我们采用自我寄宿(Self-Hostin)和IIS寄宿两种服务寄宿方式。对于前者,我们通过一个控制台应用作为服务的宿主;对于后者,则将服务寄宿于IIS的工作进程(W3WP.exe)。客户端通过另一个控制台应用模拟(进程为Client.exe)。接下来一步一步来构建这样的一个WCF应用。
步骤一:构建整个解决方案
通过VS2015创建一个空白的解决方案,起名为WcfServices并添加如下图所示的4个项目。
4个项目类型、承载的功能和相互引用如下。
- Service.Interface:用于定义服务契约(Service Contract)的类库项目,引用WCF的核心程序集System.ServiceModel.dll。
- Service:用于定义服务类型的类库项目。由于服务类型需要实现定义在Service.Interface中相应的契约接口,因此该项目具有对Service.Interface项目的引用。
- Hosting:作为服务宿主的控制台引用。该项目同时引用Service.Interface、Service项目和System.ServiceModel.dll程序集。
- Client:一个控制台应用模拟服务的客户端,该项目引用System.ServiceModel程序集。
步骤二:创建服务契约
从功能上讲,服务契约抽象了服务提供的所有操作;而站在消息交换的角度来看,服务契约则定义了基于服务调用的消息交换过程中请求消息和回复消息的结构,以及采用的消息交换模式,我们一般讲服务契约定义成接口。
如下面的代码片段所示,我们通过将System.ServiceModel.ServiceContractAttribute特性应用在接口ICalculator上从而将其定义成了服务契约。在应用ServiceContractAttribute特性的同时,还可以指定服务契约的名称(CalculatorService)和命名空间(http://www.artech.com/)。
using System.ServiceModel;
namespace Artech.WcfService.Service.Interface
{
[ServiceContract(Name = "CalculatorService",
Namespace = "http://www.artech.com/")]
public interface ICalculator
{
[OperationContract]
double Add(double x, double y);
[OperationContract]
double Subtract(double x, double y);
[OperationContract]
double Multiply(double x, double y);
[OperationContract]
double Divide(double x, double y);
}
}
通过应用ServiceContractAttribute特性将接口定义成服务契约之后,接口的方法并不能自动成为服务操作。WCF采用的是显示选择(Explicit Opt-in)的策略,意味着我们需要在相应的操作方法上面显示地应用OperationContractAttribute特性。
步骤三:创建服务
当契约接口ICalculator成功创建后,我们在Service项目中创建实现它的服务CalculatorService。如下面的代码片段所示,CalculatorService实现了接口ICalculator中的4个表示加、减、乘和除的运算方法。