对于WCF,我们有了前面的理论基础,今天通过一个计算器的实例主要给大家讲解怎么一步一步地创建一个完整的WCF应用。
一、创建整个解决方案
Calculator.Service:一个类库项目,定义服务契约(Service Contract),应用System.ServiceModel程序集;提供对WCF服务的实现。
Calculator.Host:一个Windows窗体应用程序,实现对定义在Calculator.Service项目中的服务的寄宿,该项目需要引用Calculator.Service项目和System.ServiceModel程序集。
Calculator.Client:一个Windows窗体应用程序模拟服务的客户端,该项目应用System.ServiceModel程序集。
二、创建服务契约
一般,我们通过接口的形式定义服务契约。通过下面的代码,将一个接口ICalculator定义成服务契约。我们通过在接口上应用System.ServiceModel.ServiceContractAttribute特性将一个接口定义成服务契约。
将接口定义成服务契约后,接口的方法成员并不能自动成为服务的操作。我们需要在相应的操作方法上面显式地应用OperationContractAttribute特性。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace Calculator.Service { [ServiceContract] 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); } }
三、创建服务
当服务契约创建成功后,我们需要通过实现服务契约来创建具体的WCF服务,WCF服务CalculatorService实现了服务契约的接口ICalculator,实现了所有的服务操作。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calculator.Service { public class CalculatorService:ICalculator { public double Add(double x, double y) { return x + y; } public double Subtract(double x, double y) { return x - y; } public double Multiply(double x, double y) { return x * y; } public double Divide(double x, double y) { return x / y; } } }
四、通过自我寄宿的方式寄宿服务
服务寄宿的目的就是开启一个进程,为WCF服务提供一个运行的环境。通过为服务添加一个或多个中级诶单,使之暴露给潜在的服务消费者。服务消费者最终通过相匹配的终结点对该服务进行调用。我们完全可以通过代码的方式完成所有的服务寄宿工作。
using Calculator.Service; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using System.Windows.Forms; namespace Calculator.Host { public partial class Form1 : Form { public Form1() { InitializeComponent(); } ServiceHost host = null; private void btnOpen_Click(object sender, EventArgs e) { host = new ServiceHost(typeof(CalculatorService)); host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://localhost:8008/Calculator"); if (host.Description.Behaviors.Find<ServiceMetadataBehavior>()==null) { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://localhost:8008/Calculator/metadata"); host.Description.Behaviors.Add(behavior); } host.Opened += delegate { label1.Text = "服务已经启动!"; }; host.Open(); } private void btnClose_Click(object sender, EventArgs e) { if (host.State != CommunicationState.Closed) { host.Closed += delegate { label1.Text = "服务已经停止!"; }; host.Close(); } } } }
五、创建客户端调用服务
服务被成功寄宿后,服务端便开始了服务调用请求的监听工作。此外,服务寄宿将服务描述通过元数据的形式发布出来,相应的客户端就可以获取这些元数据,创建爱你客户端程序进行服务的消费。在VS下,当我们添加服务引用的时候,VS在内部帮我们实现元数据的获取,并借组这些元数据通过代码生成工具自动生成用于服务调用的服务代理相关代码和相应的配置。
我们可以创建CalculatorClient对象,执行相应方法调用服务操作。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Calculator.Client { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { comboBox1.Text = "+"; } private void button1_Click(object sender, EventArgs e) { CalculatorService.CalculatorClient client = new CalculatorService.CalculatorClient(); double x = Convert.ToDouble (textBox1.Text); double y = Convert.ToDouble(textBox2.Text); double result=0; string operater = comboBox1.Text; switch (operater ) { case "+": result = client.Add(x, y); break; case "-": result = client.Subtract(x, y); break; case "*": result = client.Multiply(x, y); break; case "/": if (y==0) { MessageBox.Show("除数不能为0!"); return; } result = client.Divide(x, y); break; } label1.Text = textBox1.Text + comboBox1.Text + textBox2.Text + " = " + Convert.ToString(result); } } }
在这个计算器实例中,我们实现了一个简单的计算服务(CalculatorService),提供基本的加、减、乘、除的运算。客户端和服务通过运行在不同进程模拟,体现了客户端和服务端进程互相调用的关系。