湖边的白杨树

探索是一种乐趣

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

实例一: 构建一个简单的WCF Service: MagicEightBall (问问题,自动回答)

首先回顾一下WCF程序集之间的关系,理解WCF Host和Client之间的通信架构

实现WCF通信的思路就是: 

创建WCF Service(包括定义Contract和Service,配置Config文件) -> 承载(寄宿)宿主(Host) -> 客户端程序创建Proxy,实现和WCF Service进行通信。

 

具体步骤如下: 

1. 创建Contracts类库,创建WCF Service的接口 IEightBall 。

   1)添加引用(.NET)System.ServiceModel.dll程序集,并引用System.ServiceModel命名空间。

   2)将WCF Service接口标记 [ServiceContract]特性,每个接口成员标记[OperaionContract]特性。

 

C#代码 
  1. <span style="">using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. using System.ServiceModel;  
  7.   
  8. namespace Contracts  
  9. {  
  10.     //为了使接口称为WCF Services接口,必须用[ServiceContract]特性加以标记  
  11.     [ServiceContract]  
  12.     public interface IEightBall  
  13.     {  
  14.         //Ask one question ,and then get an answer.  
  15.         //WCF框架中使用的方法必须用[OperationContract]特性来修饰。  
  16.         [OperationContract]          
  17.         string ObtainAnswerToQuestion(string userQuestion);   
  18.     }  
  19. }</span>  

 

 

 

2. 创建Services类库,对Service接口IEightBall进行实现。

   1)添加引用Contracts Project,并在代码中引用Contracts命名空间。

   2)定义对接口实现的具体的内容。

 

 

C#代码 
  1. <span style="">using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. using Contracts;  
  7.   
  8. namespace Services  
  9. {  
  10.     public class EightBallService : IEightBall   
  11.     {  
  12.         //Constractor , just display message in Host.  
  13.         public EightBallService()  
  14.         {  
  15.             Console.WriteLine("The 8-ball awaits your question... ");  
  16.         }     
  17.   
  18.         //Services method for interface   
  19.         public string ObtainAnswerToQuestion(string userQuestion)  
  20.         {  
  21.             string[] answers = { "Future Uncertain""Yes""No""Hazy""Ask again later""Definitely" };  
  22.   
  23.             //Return random answer.  
  24.             Random r = new Random();  
  25.             return answers[r.Next(answers.Length)];  
  26.         }  
  27.     }  
  28. }  
  29. </span>  

 

 

3. 创建Host控制台程序,承载(寄宿)WCF Service (产品级的服务一般用Windows Service 或 IIS 虚拟目录承载)

 

   在创建WCF Service的Host时,需要决定在代码中定义必要的承载逻辑,还是配置相关的Config文件。 配置Config文件的好处在于Host可以改变底层的运行方式而不用重新编译和部署可执行文件。

 

   构建WCF Service的Host的一般步骤为: 

   (I)在Host的配置文件中,定义所承载的WCF Service 的 终结点(Endpoint)。

   (II)通过编程使用ServiceHost类型去提供 Endpoint所提供的Service类型。

   (III)确保Host保持运行状态,以处理所受到的客户端请求。(显然,Windows Service 或 IIS 不需要这一步 )

 

   具体实现如下:

   1)向当前项目中添加一个Application Configuration File (App.conifg). 在App.config文件中创建ABC ,

     在WCF的世界中,终结点(Endpoint)是表示A(地址),B(绑定),C(契约)的一个包装。

 在XML中,终结点使用<endpoint>元素,和address,binding,contract 元素进行表达。

 

 

Xml代码 
  1. <span style=""><?xml version="1.0" encoding="utf-8" ?>  
  2. <configuration>  
  3.   <system.serviceModel>  
  4.     <services>  
  5.       <service name="Services.EightBallService">  
  6.         <endpoint address ="http://localhost:8080/EightBallService"  
  7.                   binding ="basicHttpBinding"  
  8.                   contract ="Contracts.IEightBall"/>  
  9.       </service>  
  10.     </services>  
  11.   </system.serviceModel>  
  12. </configuration></span>  

 

 

   2)针对ServiceHost类型进行编程。创建ServiceHost实例,在运行时,这个对象会自动读取Host 中*.config文件中<system.serviceModel>元素中的数据来检测正确的地址,绑定类型和契约,然后创建必要的管道。

   2.1)添加对System.ServiceModel.dll 和 本例中 Services project (即Services.dll) 的引用。

   2.2)代码中引用System.ServiceModel , Services 命名空间

   2.3)启用元数据交换

       - 元数据交换(MEX)是一个WCF Service Behaviors,可以指定它微调WCF运行库如何处理我们的Service

   - MEX行为会通过HTTP-GET拦截任何元数据请求。如果希望用svcutil.exe或者VS2010来自动创建客户端代理的*.config文件,必须启用MEX。

   修改Host的App.config文件如下:

   

 

Xml代码 
  1. <span style=""><?xml version="1.0" encoding="utf-8" ?>  
  2. <configuration>  
  3.   <system.serviceModel>  
  4.     <services>  
  5.       <service name="Services.EightBallService"  
  6.                behaviorConfiguration ="MEXBehavior">  
  7.         <endpoint address=""  
  8.                   binding="basicHttpBinding"  
  9.                   contract="Contracts.IEightBall"/>  
  10.   
  11.         <!-- Enable MEX endpoint-->  
  12.         <endpoint address="mex"  
  13.                   binding="mexHttpBinding"  
  14.                   contract="IMetadataExchange"/>  
  15.   
  16.         <!-- Let MEX know the address of Service-->  
  17.         <host>  
  18.           <baseAddresses>  
  19.             <add baseAddress="http://localhost:8080/Services/EightBallService"/>  
  20.           </baseAddresses>  
  21.         </host>  
  22.       </service>  
  23.     </services>  
  24.   
  25.     <!-- Define behavior of MEX-->  
  26.     <behaviors>  
  27.       <serviceBehaviors>  
  28.         <behavior name="MEXBehavior">  
  29.           <serviceMetadata httpGetEnabled="true"/>  
  30.         </behavior>  
  31.       </serviceBehaviors>  
  32.     </behaviors>  
  33.   
  34.   </system.serviceModel>  
  35. </configuration>  
  36. </span>  

 

   

 

Host代码如下:

 

 

C#代码 
  1. <span style="">using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. using System.ServiceModel;  
  7. using Services;  
  8.   
  9. namespace TestServiceHost  
  10. {  
  11.     class Program  
  12.     {  
  13.         static void Main(string[] args)  
  14.         {  
  15.             Console.WriteLine(" Console Based WCF Host ");  
  16.             using (ServiceHost serviceHost = new ServiceHost(typeof(EightBallService)))  
  17.             {  
  18.                 //Open host and keep listenning from client.   
  19.                 serviceHost.Open();  
  20.   
  21.                 //Display host control application windows, and don't exist unless Enter key is pressed.  
  22.                 Console.WriteLine(" The service is ready. Press the Enter key to terminate service. ");  
  23.                 Console.ReadLine();  
  24.             }  
  25.         }  
  26.     }  
  27. }  
  28. </span>  

 

 

运行这个应用程序后(run as administrator),宿主在内存中随时准备接受从远程客户端发来的请求。

可以用Web浏览器来查看元数据描述。http://localhost:8080/Services/EightBallService

 

 

 

补充1: <system.serviceModel>元素的细节

 

Xml代码 
  1. <span style=""><system.serviceModel>  
  2.   <behaviors></behaviors>        <!-- 进一步限定Host,Service或Client端的功能。-->  
  3.   <client></client>              <!-- 包含客户端来连接到Service的endpoint列表。-->  
  4.   <commonBehaviors></commonBehaviors>       <!-- 定义了允许WCF和COM互操作的COM契约-->  
  5.   <diagnostics></diagnostics>    <!-- 包含WCF诊断特新的设置,可以启用或禁用跟踪,性能计数器,和WMI提供程序,并且可以增加自定义消息过滤器-->  
  6.   <comContracts></comContracts>  <!-- 这个元素只能在machine.config文件中进行设置,可以用于定义某个机器所有的WCF的行为-->  
  7.   <services></services>          <!-- 包含了从Host公开的WCF Service的集合 -->  
  8.   <bindings></bindings>          <!-- 允许我们微调WCF提供的绑定如basicHttpBinding和netMsmqBing等-->  
  9. </system.serviceModel>  
  10. </span>  

 

 

4. 创建一个控制台项目,构建WCF Client端应用程序。 

   1)首先需要创建客户端代理(proxy)  (注:之前需要使Host程序保持运行,即使WCF Service保持运行状态)

   方法一: 使用svcutil.exe 生成代理代码

   svcutil http://localhost:8080/EightBallService/out:myProxy.cs /config:app.cofig

 

   方法二: 使用VS2010生成代理代码。

   1.1) 在Client控制台项目中,Add Service Reference。然后在Address里面输入Service的Uri: http://localhost:8080/EightBallService

   1.2) 点击go查看Service 描述。命名为 EightBallServiceReference 后保存退出。

        - 工具会自动生成客户端的代理类EightBallClient代码。

 

   2)编写客户端控制台代码

 

 

C#代码 
  1. <span style="">using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. // Proxy location  
  7. using Client.EightBallServiceReference;  
  8.   
  9. namespace Client  
  10. {  
  11.     class Program  
  12.     {  
  13.         static void Main(string[] args)  
  14.         {  
  15.             Console.WriteLine(" Ask the Magic 8 Ball . \n");  
  16.   
  17.             using (EightBallClient ball = new EightBallClient())  
  18.             {  
  19.                 Console.Write("Your questoin:");  
  20.                 string question = Console.ReadLine();  
  21.                 string answer = ball.ObtainAnswerToQuestion(question);  
  22.                 Console.WriteLine("8-ball syas:{0}", answer);  
  23.             }  
  24.             Console.ReadLine();  
  25.         }  
  26.     }  
  27. }</span>  

 

 

至此,我们在Client端运行Client.exe程序,就可以通过Service代理类来运行WCF Service 中的方法了。 实现了Client端和Server端的通信。

 

posted on 2013-01-13 19:06  fdyang  阅读(473)  评论(0编辑  收藏  举报