Windows Communication Foundation(WCF)是一个面向服务(SOA)的通讯框架,作为.NET Framework 3.0的重要组成部分于2006年正式发布。WCF的使命是对Windows平台下现有的通讯技术(包括:COM、DCOM、.NET Remoting、Web Services、MSMQ、WinSocket)进行全面整合,并设计了一个统一的程序开发模型(API),对于数据通信提供了最基本最有弹性的支持。借助这一模型,开发人员可以构建既能跨平台与现有投资集成又能与现有投资交互的安全、可靠的事务处理解决方案。
下面的示例阐释了 WCF 处理的一些问题。一家汽车租赁公司决定创建一个新的应用程序,用于汽车预定。该租车预定应用程序的创建者知道,应用程序所实现的业务逻辑必须能够让公司内外运行的其他软件访问。因此,他们决定以面向服务的方式来创建此应用程序,并通过定义完善的一组服务,将此应用程序的逻辑公开给其他软件。为了实现这些服务并使之与其他软件进行通信,这一新应用程序将使用 WCF。
在租车预定应用程序的生存期内,可能会有一系列其他应用程序访问此应用程序。但是在设计期间设计者知道,将有其他三种软件访问该租车预定应用程序的业务逻辑(如上图所示):
- 运行在 Windows 桌面上的呼叫中心客户端应用程序,它由该组织的呼叫中心员工使用。此应用程序是专门针对新的预定系统创建的,也可以使用 Microsoft .NET Framework 和 WCF 来构建。此应用程序与新的租车预定应用程序并不泾渭分明,因为它的唯一用途是作为该新系统的客户端。从面向服务的角度来看,它只是该预定系统的业务逻辑的另一个客户端。
- 基于 J2EE 服务器构建、在非 Windows 系统上运行的现有预定应用程序。由于最近与另一家汽车租赁公司合并,此现有系统必须能够访问新应用程序的逻辑,以便为合并后公司的客户提供一致的体验。
- 运行在各种平台上的合作伙伴应用程序,每个应用程序分别位于一个与该汽车租赁公司有业务合作的公司内。合作伙伴可能包括旅行社、航空公司,以及具有租车预定业务需求的其他组织。
下面是wcf体系结构图:
WCF寄宿:
首先WCF应用程序是不能独立存在的,它必须依附于(寄宿)于其他的应用程序(宿主)中,宿主进程是专为承载服务而设计的应用程序。这些宿主进程包括 Internet 信息服务 (IIS)、Windows 激活服务 (WAS) 和 Windows 服务、开发人员创建的应用程序。
下面我们通过一个简单的示例程序来学习如何构建一个WCF程序,以便于对WCF编程建立一个初步的印象。我们创建一个计算器服务,实现简单的加、减、乘、除的操作,然后由另一个进程(本地或远程)来调用这个服务。
1.首先我们创建一个名为:HelloWcfService解决方案,在该解决方案下创建一个Hosting的控制台项目;用于承载WCF服务。接着创建一个ContractService类库项目,定于定于服务的契约(接口);再最后创建一个Service类库项目,用于实现ContractService定义的服务契约(接口)。如下:
2.从字面上来理解,服务契约就是:服务所提供操作的一个抽象。服务契约指定了服务支持的操作,通过使用接口来创建契约,接口中的每个方法都应对与特定的服务操作,同时定义契约的接口必须应用ServiceContractAttribute特性,同时我们需要在接口中定义的方法应用OperationContractAttribute特性,否则不公开该方法。
我们在创建的解决方案中的ContractService类库项目中引用System.ServiceModel程序集,并添加System.ServiceModel命名空间,接着创建一个用于定义服务契约的接口,代码如下:
1 using System.ServiceModel; 2 3 namespace ContractService 4 { 5 [ServiceContract(Name = "CalculatorService", Namespace = "ContractService")] 6 public interface ICalculator 7 { 8 [OperationContract] 9 double Add(double num1, double num2);//加法 10 [OperationContract] 11 double Subtract(double num1, double num2);//减法 12 [OperationContract] 13 double Multiply(double num1, double num2);//乘法 14 [OperationContract] 15 double Divide(double num1, double num2);//除法 16 } 17 }
3.在前面我们只是对服务具有哪些操作进行一个抽象的定义,我们需要这个抽象的契约进行实现。在我们的这个例子中就是实现ICalculator接口。首先我们在Service的类库项目添加对ContractService类库项目的引用,并添加ContractService命名空间,然后实现ICalcultor接口,代码如下:
1 using System; 2 using ContractService; 3 4 namespace Service 5 { 6 public class CalculatorService : ICalculator 7 { 8 #region ICalculator 成员 9 10 /// <summary>加法</summary> 11 public double Add(double num1, double num2) 12 { 13 return num1 + num2; 14 } 15 16 /// <summary>减法</summary> 17 public double Subtract(double num1, double num2) 18 { 19 return num1 - num2; 20 } 21 22 /// <summary>乘法</summary> 23 public double Multiply(double num1, double num2) 24 { 25 return num1 * num2; 26 } 27 28 /// <summary>除法</summary> 29 public double Divide(double num1, double num2) 30 { 31 return num1 / num2; 32 } 33 34 #endregion 35 } 36 }
4.通过前面我们知道WCF服务是无法独立存在在,它必须是寄宿于其他的宿主(应用程序)中,寄宿服务的对象可以是开发人员自己创建的应用程序可以使用IIS和Windows服务等作为服务的宿主。在这里我们通过创建的控制台程序来作为服务的宿主。
5.在解决方案的Hosting项目中添加对System.ServiceModel程序集,Service项目以及ContractService类库项目的引用,并添加相应的命名空间。代码如下
1 static void Main(string[] args) 2 { 3 //定义承载服务的类型和承载服务的基址 4 using (ServiceHost host = new ServiceHost(typeof(CalculatorService), new Uri("http://localhost:8889/CalculatorService"))) 5 { 6 //增加一个服务终结点 7 host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService"); 8 9 //使用元数据 10 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); 11 //使用HTTP/GET请求 12 behavior.HttpGetEnabled = true; 13 //定义元数据发布地址 14 behavior.HttpGetUrl = new Uri("http://localhost:8889/CalculatorService/Metadata"); 15 //将元数据的定义添加到承载服务中 16 host.Description.Behaviors.Add(behavior); 17 18 // 启动服务 19 host.Open(); 20 Console.WriteLine("CalculatorService服务运行中...\n"); 21 Console.WriteLine("按任意键退出."); 22 Console.Read(); 23 // 关闭服务 24 host.Close(); 25 } 26 }
运行宿主程序后,我们在浏览器中输入下面的地址进行查看服务是否成功运行:
- 服务的地址:http://localhost:8889/CalculatorService
- 元数据的地址:http://localhost:8889/CalculatorService/Metadata
5.调用WCF服务:
前面我们已经成功的创建一个可以用于基础运算的WCF服务,我们创建一个HelloWcfClient控制台应用程序用来调用前面WCF提供的服务,我们通过这个服务发布的元数据来生成调用代码(使用Svcutil.exe工具)Visual Studio可以为我们简化这一过程:运行WCF服务的宿主程序后,为HelloWcfClient项目添加服务引用,服务的地址就是前面创建的元数据地址:http://localhost:8889/CalculatorService/Metadata ,Visual Studio会自动生成一系统服务调用的代码和配置:
只需要几行代码就可以完成服务的调用,调用代码如下:
1 static void Main(string[] args) 2 { 3 using (CalculatorServiceClient proxy = new CalculatorServiceClient()) 4 { 5 Console.WriteLine("{0}+{1}={2}", 1, 2, proxy.Add(1, 2)); 6 Console.WriteLine("{0}-{1}={2}", 5, 2, proxy.Subtract(5, 2)); 7 Console.WriteLine("{0}*{1}={2}", 1, 2, proxy.Multiply(1, 2)); 8 Console.WriteLine("{0}/{1}={2}", 1, 2, proxy.Divide(1, 2)); 9 } 10 Console.Read(); 11 }
运行结果如下: