创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址
一、创建WCF服务器
1、创建WCF服务器的窗体应用程序
打开VS2010,选择文件→新建→项目菜单项,在打开的新建项目对话框中,依次选择Visual C#→Windows→Windows窗体应用程序,然后输入项目名称(Name),存放位置(Location)和解决方案名称(Solution Name),点击“确定”生成项目。如下图:
2、在新建的WcfServer项目中右键添加→新建项,新建一个Calculate的WCF服务,接着添加服务操作,本示例中添加了一个Add的加法服务操作
Add的加法服务操作代码:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServer { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“ICalculate”。 [ServiceContract] public interface ICalculate { [OperationContract] int Add(int i, int j); } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServer { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Calculate”。 public class Calculate : ICalculate { public int Add(int i, int j) { return i + j; } } }
3、将该项目中创建的Form1重命名为FrmMain,在窗体中进行WCF服务的操作,如下图:
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; using System.ServiceModel; using System.Configuration; using System.ServiceModel.Configuration; namespace WcfServer { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); txtWcfServiceURL.Text = ConfigHelper.Config.WcfServiceConnectURL; } /// <summary> /// 主机服务 /// </summary> ServiceHost serviceHost; /// <summary> /// 开启服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { ConfigHelper.Config.WcfServiceConnectURL = txtWcfServiceURL.Text; if (serviceHost == null) { this.btnStart.Enabled = false; this.btnStop.Enabled = true; try { // 实例化WCF服务对象 serviceHost = new ServiceHost(typeof(WcfServer.Calculate)); serviceHost.Opened += delegate { MessageBox.Show("启动服务OK"); }; serviceHost.Closed += delegate { MessageBox.Show("停止服务OK"); }; serviceHost.Open(); } catch (Exception ex) { MessageBox.Show("启动服务异常:" + ex.Message + "==>" + ex.StackTrace); } } else { btnStop_Click(sender, e); } } /// <summary> /// 停止服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStop_Click(object sender, EventArgs e) { this.btnStart.Enabled = true; this.btnStop.Enabled = false; try { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } } catch (Exception ex) { MessageBox.Show("停止服务异常:" + ex.Message + "==>" + ex.StackTrace); } } } public class ConfigHelper { private static ConfigHelper _config = new ConfigHelper(); /// <summary> /// 获取ServerConfig对象 /// </summary> public static ConfigHelper Config { get { return _config; } } /// <summary> /// 获取或设置连接服务器地址 /// </summary> public string WcfServiceConnectURL { get { return GetWcfServiceUri(); } set { SetWcfServiceUri(value); } } /// <summary> /// 设置Wcf服务器的地址 /// </summary> private void SetWcfServiceUri(string uri) { Configuration serviceModelConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSectionGroup serviceModel = serviceModelConfig.SectionGroups["system.serviceModel"]; ServiceModelSectionGroup serviceModelSectionGroup = serviceModel as ServiceModelSectionGroup; ServiceElement service = serviceModelSectionGroup.Services.Services["WcfServer.Calculate"]; service.Host.BaseAddresses[0].BaseAddress = uri; serviceModelConfig.Save(); // 刷新命名节,在下次检索它时将从磁盘重新读取它。记住应用程序要刷新节点 //ConfigurationManager.RefreshSection("system.serviceModel"); ConfigurationManager.RefreshSection("system.serviceModel/behaviors"); ConfigurationManager.RefreshSection("system.serviceModel/bindings"); ConfigurationManager.RefreshSection("system.serviceModel/client"); ConfigurationManager.RefreshSection("system.serviceModel/services"); } /// <summary> /// 获取Wcf服务器的地址 /// </summary> /// <returns></returns> private string GetWcfServiceUri() { Configuration serviceModelConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSectionGroup serviceModel = serviceModelConfig.SectionGroups["system.serviceModel"]; ServiceModelSectionGroup serviceModelSectionGroup = serviceModel as ServiceModelSectionGroup; ServiceElement service = serviceModelSectionGroup.Services.Services["WcfServer.Calculate"]; return service.Host.BaseAddresses[0].BaseAddress; } /// <summary> /// 设置指定节点的配置值 /// </summary> private void SetAppSettings(string key, string value) { Configuration appSettingConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); appSettingConfig.AppSettings.Settings[key].Value = value; appSettingConfig.Save(); ConfigurationManager.RefreshSection("appSettings");// 刷新命名节,在下次检索它时将从磁盘重新读取它。记住应用程序要刷新节点 } /// <summary> /// 获取指定节点的配置值 /// </summary> private string GetAppSettings(string key) { return ConfigurationManager.AppSettings[key]; } } }
这样WCF服务器基本上就做好了,接下来就是在WCF客户端调用了!
二、WCF客户端
1、新建的控制台程序项目WcfClient,右键添加服务引用,弹出添加服务引用对话框,点击前往,在地址上输入WCF服务器的地址,找到服务后,修改命名空间,点击确定,项目自动生成服务。如下图:
2、客户端(控制台应用程序)中调用WCF服务操作
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; namespace WcfClient { class Program { // 要想异步调用,需要在添加服务引用时,选择“高级”按钮→勾选“生成异步操作” static void Main(string[] args) { EndpointAddress endPoint = new EndpointAddress("http://192.168.8.184/Calculate"); // 基于WSHttp请求方式 Binding wshttpBinding = new WSHttpBinding(); wshttpBinding.SendTimeout = new System.TimeSpan(0, 1, 0); // 手动调用WCF地址 WcfService.CalculateClient calcTest = new WcfService.CalculateClient(wshttpBinding, endPoint); // 进行异步操作 calcTest.AddCompleted += new EventHandler<WcfService.AddCompletedEventArgs>(calcTest_AddCompleted); calcTest.AddAsync(12, 21); Console.ReadKey(); } /// <summary> /// 调用AddAsync方法完成后回调事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> static void calcTest_AddCompleted(object sender, WcfService.AddCompletedEventArgs e) { Console.WriteLine(e.Result); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; namespace WcfClient { class Program { static void Main(string[] args) { WcfService.ICalculate icalcTest = null; try { EndpointAddress endPoint = new EndpointAddress("http://192.168.8.184/Calculate"); // 基于WSHttp请求方式 Binding wshttpBinding = new WSHttpBinding(); //using (ChannelFactory<WcfService.ICalculate> channelFactory = new ChannelFactory<WcfService.ICalculate>("ClientEndpoint", endPoint)) using (ChannelFactory<WcfService.ICalculate> channelFactory = new ChannelFactory<WcfService.ICalculate>(wshttpBinding, endPoint)) { icalcTest = channelFactory.CreateChannel(); // 建立连接通道 (icalcTest as ICommunicationObject).Closed += delegate { Console.WriteLine("连接已关闭"); }; int addResult = icalcTest.Add(12, 21); Console.WriteLine(addResult); } } catch (TimeoutException) { (icalcTest as ICommunicationObject).Abort(); } catch (CommunicationException) { (icalcTest as ICommunicationObject).Abort(); } catch (Exception) { (icalcTest as ICommunicationObject).Close(); } Console.ReadKey(); } } }