WCF开发框架形成之旅---WCF的几种寄宿方式

WCF寄宿方式是一种非常灵活的操作,可以在IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解。

1、 WCF服务的IIS服务寄宿

我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿。这种寄宿方式是最为方便的方式,而且由于服务只需要IIS运行就能自动运行起来,因此广为使用。

创建这种方式IIS寄宿方式的,只需要在解决方案里面,添加WCF服务应用程序,就可以生成这种的服务模块了。

这个是一个基于Web的应用程序,创建项目后会生成一个Service1.svc的服务页面,以及相关的WCF服务接口和实现,如下图所示。

这个就是简单的WCF服务,当然如果是复杂的实际应用,会考虑和数据库打交道,而且可能项目会分成几个进行管理,从而实现更好的逻辑分离操作。

2、 创建WCF服务库为多种寄宿做准备

除了上面常用的IIS服务寄宿,一般还会有各种各样的寄宿方式,不过如果采用其他方式的寄宿方式,一般会把WCF服务和寄宿方式进行项目的分离,实现更好的重用操作,特别WCF需要考虑多种寄宿方式的情况下。下面是WCF服务库和WCF服务应用程序的介绍说明,先了解一下基础。

WCF服务库,可以认为是一个包含WCF服务以及契约定义的类库。这里WCF服务库还不能直接运行,你可以在其他项目里引用,在宿主里启用托管这个库。

而WCF应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定义,可以直接看到运行的效果。此项目模板应该是基于IIS托管的程序。

前者一般考虑WCF服务设计的时候,服务类的定义为单独的库,可以为其它项目使用。提高代码的复用性。后者在开发基于IIS托管的WCF服务程序时,比较多见,自学的时候也可以使用这种类型。当然你也可以修改这些代码,比如把WCF服务程序里的类,移到一个单独的类库里。

创建WCF服务库,可以理解为我们开发.NET程序时创建的一个类库模块,不含界面,如下所示,创建一个WCF服务库。

确定后就只有一个示例服务Service1生成了。

这里,我们为了演示,就不修改任何它们的代码,原始的代码如下所示。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.Text;
  7.  
  8. namespace WcfServiceLibrary
  9. {
  10. public class Service1 : IService1
  11. {
  12. public string GetData(int value)
  13. {
  14. return string.Format("You entered: {0}", value);
  15. }
  16.  
  17. public CompositeType GetDataUsingDataContract(CompositeType composite)
  18. {
  19. if (composite == null)
  20. {
  21. throw new ArgumentNullException("composite");
  22. }
  23. if (composite.BoolValue)
  24. {
  25. composite.StringValue += "Suffix";
  26. }
  27. return composite;
  28. }
  29. }
  30. }

3、 WCF服务的控制台程序寄宿

这种也是一种常见的WCF服务寄宿方式,通过启动一个类似DOS窗口的控制台软件,实现WCF服务的动态寄宿,关闭控制台程序,服务就自然终止。

这种方式很简单,创建一个控制台程序,然后添加WCF服务类库的项目应用,在Main函数里面添加下面代码即可实现。

  1. namespace WcfService_HostConsole
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. try
  8. {
  9. ServiceHost serviceHost = new ServiceHost(typeof(Service1));
  10. if (serviceHost.State != CommunicationState.Opened)
  11. {
  12. serviceHost.Open();
  13. }
  14.  
  15. Console.WriteLine("WCF 服务正在运行......");
  16. Console.WriteLine("输入回车键 <ENTER> 退出WCF服务");
  17. Console.ReadLine();
  18. serviceHost.Close();
  19.  
  20. }
  21. catch (Exception ex)
  22. {
  23. Console.WriteLine(ex);
  24. }
  25. }
  26. }
  27. }

4、 WCF服务的Winform程序寄宿

和控制台程序一样,我们创建一个Winform项目,然后在窗体启动代码里面添加寄宿方式的代码即可,为了较好的响应体验,可以使用后台线程程序进行服务启动,如下所示。

  1. namespace WcfService_HostWinform
  2. {
  3. public partial class FrmMain : Form
  4. {
  5. ServiceHost serviceHost = null;
  6. BackgroundWorker worker = null;
  7.  
  8. public FrmMain()
  9. {
  10. InitializeComponent();
  11.  
  12. worker = new BackgroundWorker();
  13. worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
  14. worker.DoWork += new DoWorkEventHandler(worker_DoWork);
  15.  
  16. if (!worker.IsBusy)
  17. {
  18. tssTips.Text = "正在启动......";
  19. lblTips.Text = tssTips.Text;
  20. worker.RunWorkerAsync();
  21. }
  22. }
  23.  
  24. void worker_DoWork(object sender, DoWorkEventArgs e)
  25. {
  26. try
  27. {
  28. serviceHost = new ServiceHost(typeof(Service1));
  29. if (serviceHost.State != CommunicationState.Opened)
  30. {
  31. serviceHost.Open();
  32. }
  33.  
  34. e.Result = "正常";
  35. }
  36. catch (Exception ex)
  37. {
  38. e.Result = ex.Message;
  39. }
  40. }
  41.  
  42. void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  43. {
  44. if (e.Result != null)
  45. {
  46. if (e.Result.ToString() == "正常")
  47. {
  48. tssTips.Text = "服务正在进行侦听......";
  49. }
  50. else
  51. {
  52. tssTips.Text = string.Format("错误:{0}", e.Result);
  53. }
  54.  
  55. lblTips.Text = tssTips.Text;
  56. }
  57. }
  58. ...........................
  59. }
  60. }

当然为了防止Winform程序被不小心关闭,可以添加托盘代码,把程序缩小到托盘图标里面。

5、 WCF服务的Windows 服务程序寄宿

这种方式的服务寄宿,和IIS一样有一个一样的优点,系统启动后,WCF服务也会跟着启动了,不用人工干预,也是一种较好的寄宿方式。

为了实现这种方式的寄宿,我们创建一个控制台程序,然后添加响应的Window服务和安装程序类

然后在服务类启动里面添加WCF的寄宿代码,如下所示。

  1. public class ServiceManager : ServiceBase
  2. {
  3. private static object syncRoot = new Object();//同步锁
  4. private ServiceHost serviceHost = null; //寄宿服务对象
  5.  
  6. public ServiceManager()
  7. {
  8. this.ServiceName = Constants.ServiceName;
  9. }
  10.  
  11. /// <summary>
  12. /// 设置具体的操作,以便服务可以执行它的工作。
  13. /// </summary>
  14. protected override void OnStart(string[] args)
  15. {
  16. try
  17. {
  18. serviceHost = new ServiceHost(typeof(Service1));
  19. if (serviceHost.State != CommunicationState.Opened)
  20. {
  21. serviceHost.Open();
  22. }
  23. }
  24. catch (Exception ex)
  25. {
  26. LogTextHelper.Error(ex);
  27. }
  28.  
  29. LogTextHelper.Info(Constants.ServiceName + DateTime.Now.ToShortTimeString() + "已成功调用了服务一次。");
  30.  
  31. LogTextHelper.Info(Constants.ServiceName + "已成功启动。");
  32. }

为了实现通过该控制台程序实现参数化安装和卸载服务,我们需要拦截控制台的参数,并进行相应的操作,如下所示。

  1. /// <summary>
  2. /// 应用程序的主入口点。
  3. /// </summary>
  4. [STAThread]
  5. static void Main(string[] args)
  6. {
  7. ServiceController service = new ServiceController(Constants.ServiceName);
  8.  
  9. // 运行服务
  10. if (args.Length == 0)
  11. {
  12. ServiceBase[] ServicesToRun;
  13. ServicesToRun = new ServiceBase[] { new ServiceManager() };
  14. ServiceBase.Run(ServicesToRun);
  15. }
  16. else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i")
  17. {
  18. #region 安装服务
  19. if (!ServiceIsExisted(Constants.ServiceName))
  20. {
  21. try
  22. {
  23. string[] cmdline = { };
  24. string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
  25.  
  26. TransactedInstaller transactedInstaller = new TransactedInstaller();
  27. AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
  28. transactedInstaller.Installers.Add(assemblyInstaller);
  29. transactedInstaller.Install(new System.Collections.Hashtable());
  30.  
  31. TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10);
  32. service.Start();
  33. service.WaitForStatus(ServiceControllerStatus.Running, timeout);
  34. }
  35. catch (Exception ex)
  36. {
  37. LogTextHelper.Info(ex);
  38. throw;
  39. }
  40. }
  41. #endregion
  42. }
  43. else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u")
  44. {
  45. #region 删除服务
  46. try
  47. {
  48. if (ServiceIsExisted(Constants.ServiceName))
  49. {
  50. string[] cmdline = { };
  51. string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
  52.  
  53. TransactedInstaller transactedInstaller = new TransactedInstaller();
  54. AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
  55. transactedInstaller.Installers.Add(assemblyInstaller);
  56. transactedInstaller.Uninstall(null);
  57. }
  58. }
  59. catch (Exception ex)
  60. {
  61. LogTextHelper.Info(ex);
  62. throw;
  63. }
  64. #endregion
  65. }
  66. }

编译程序成功后,我们添加两个批处理的DOS脚本来实现执行程序的自动安装和卸载,如下所示。

安装脚本

  1. "WcfService_HostWinService.exe" -i
  2. pause

卸载脚本

  1. "WcfService_HostWinService.exe" -u
  2. pause

顺利执行脚本后,服务列表里面就增加一个服务项目了。

卸载操作,直接执行脚本就会卸载服务,非常方便哦。

6、 WCF服务的Web寄宿

当然,除了以上几种方式,这种以WCF服务库的方式,也可以在Web方式进行寄宿(IIS方式),这种方式更简单,添加一个后缀名的svc的文件,只需要一行代码即可,如下所示。

7、 使WCF服务支持GET方式调用

有时候,我们为了需要,可能通过一个小程序发布一个服务,然后供其他程序进行调用,可能是Web,也可以是Winform,但是我们是想提供一个基于HTTP,GET或者POST方式来实现接口的调用的,例如,提供一个JSON格式或者文本格式的内容返回操作。

如果是整合在Winform里面,那么我们在Winform里面添加一个WCF的项,修改里面的代码就可以了,如下所示。

首先要在使用GET方式的WCF服务接口的添加说明。如果是POS方式,增加设置有点不同([WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)])。

  1. namespace WcfServiceForWinform
  2. {
  3. [ServiceContract]
  4. public interface IService1
  5. {
  6. [OperationContract]
  7. void DoWork();
  8.  
  9. [OperationContract]
  10. [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
  11. string GetData(int value);
  12. }
  13. }

第二,在实现类里面添加相应的设置

  1. namespace WcfServiceForWinform
  2. {
  3. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  4. public class Service1 : IService1
  5. {
  6. public void DoWork()
  7. {
  8. }
  9.  
  10. public string GetData(int value)
  11. {
  12. return string.Format("You entered: {0}", value);
  13. }
  14. }
  15. }

配置文件如下所示,颜色标注特别的要注意:

  1. <?xml version="1.0"?>
  2. <configuration>
  3.  
  4. <system.web>
  5. <compilation debug="true"/>
  6. </system.web>
  7.  
  8. <system.serviceModel>
  9. <services>
  10. <service name="WcfServiceForWinform.Service1" behaviorConfiguration="ServiceConfig">
  11. <endpoint address="" binding="webHttpBinding"
  12. bindingConfiguration="webHttpBindingWithJsonP" behaviorConfiguration="webHttpBehavior"
  13. contract="WcfServiceForWinform.IService1">
  14. </endpoint>
  15. <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  16. <host>
  17. <baseAddresses>
  18. <add baseAddress="http://localhost:9000/Service1/" />
  19. </baseAddresses>
  20. </host>
  21. </service>
  22. </services>
  23.  
  24. <bindings>
  25. <webHttpBinding>
  26. <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
  27. </webHttpBinding>
  28. </bindings>
  29.  
  30. <behaviors>
  31. <endpointBehaviors>
  32. <behavior name="webHttpBehavior">
  33. <webHttp/>
  34. </behavior>
  35. </endpointBehaviors>
  36.  
  37. <serviceBehaviors>
  38. <behavior name="ServiceConfig">
  39. <serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/>
  40. <serviceDebug includeExceptionDetailInFaults="False"/>
  41. </behavior>
  42. </serviceBehaviors>
  43. </behaviors>
  44.  
  45. <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  46. </system.serviceModel>
  47.  
  48. <startup>
  49. <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  50. </startup>
  51. </configuration>

运行Winform程序,启动了WCF服务后,我们可以在浏览器(Chrome)上进行操作,如下结果所示。

从上图我们可以看到,这个通过Winform启动起来的WCF服务,连接也能通过GET方式进行接口调用了,接口可以通过参数进行传递,对于一些方便传输数据的接口如JSON接口,就是一种非常方便的调用了。

以上轉http://i.cnblogs.com/EditPosts.aspx?opt=1

WCF寄宿方式的更多相关文章

  1. (转)WCF开发框架形成之旅---WCF的几种寄宿方式

    WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详 ...

  2. WCF开发框架形成之旅---WCF的几种寄宿方式

    WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者 ...

  3. 微软 WCF的几种寄宿方式,寄宿IIS、寄宿winform、寄宿控制台、寄宿Windows服务

    WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详 ...

  4. [转]WCF的几种寄宿方式

    转自:WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为 ...

  5. WCF :IIS寄宿方式的Web地址、BaseAddress和EndPoint Address的关系

    对于在IIS中通过W3SVC或WAS寄宿的WCF Service,其在浏览器中显示的地址(Web地址),与其配置文件中的BaseAddress和EndPoint Address有什么关系呢?让我们来分 ...

  6. WCF引用方式之IIS方式寄宿服务

    通过IIS方式寄宿服务 之前的例子是将控制台作为WCF的寄宿方式或者是直接添加契约项目的引用,然后通过配置或者是ChannelFactory的形式进行创建服务对象,其实在大多的开发中以IIS的形式创建 ...

  7. WCF之各种WCF引用方式

    写在开头:本文内容来自 WCF全面解析中的一个经典例子,如果你已经看过了,那么可以忽略本文,本文旨在和大家分享不一样的WCF使用方法. 准备工作: 1.创建解决方案WCFService(当然名字可以任 ...

  8. WCF引用方式

    WCF之各种WCF引用方式 写在开头:本文内容来自 WCF全面解析中的一个经典例子,如果你已经看过了,那么可以忽略本文,本文旨在和大家分享不一样的WCF使用方法. 准备工作: 1.创建解决方案WCFS ...

  9. 将WCF寄宿在托管的Windows服务中

    在我之前的一篇博客中我介绍了如何发布WCF服务并将该服务寄宿于IIS上,今天我再来介绍一种方式,就是将WCF服务寄宿在Windows服务中,这样做有什么好处呢?当然可以省去部署IIS等一系列的问题,能 ...

随机推荐

  1. ElasticSearch安装部署

    官网:http://www.elasticsearch.org ElasticSearch is an open-source and distributed search engine which ...

  2. (译) Angular运行原理揭秘 Part 1

    当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...

  3. onTouch与onClick事件的关系

    这几天遇到点关于Android的触摸事件相关的,还跟onClick有关,暂且记下: LinearLayout分别设置了onTouchListener,onClickListener,onLongCli ...

  4. [原]poj-2524(裸并查集)

    题目链接: http://poj.org/problem?id=2524 题意: n个人,m对人宗教相同,输出一共有多少个不同的宗教. 代码如下: #include<iostream> # ...

  5. enable c++11 in autoconf in fucking gnu auto tools

    configure.ac => CXXFLAGS="$CXXFLAGS -std=c++14" set CXXFLAGS  => std=c++14 well done ...

  6. eclipse ADT下载地址

    adt not vpn https://dl.google.com/android/eclipse/ 或 https://dl-ssl.google.com/android/eclipse/ andr ...

  7. laravel创建新model数据的两种方法

    laravel中的CRUD操作中,通过对代表数据表中row的model对象操作,来更新数据库表. 对于创建新的row的操作,有两种功能上相同的方法: 1.create: $user = User::c ...

  8. 51nod1354 选数字

    01背包tle. 解题报告(by System Message) 类似于背包的DP,以乘积为状态.先把等选数字里面不是K约数的去掉.然后找出K的约数,进行离散化.然后dp[i][j]表示前i个数字乘积 ...

  9. wx菜单栏

    #include "MainFrame.h" BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_MENU(wxID_FILE,MyFrame::OnMe ...

  10. Eclipse实用快捷键

    经典常用快捷键1. [ALT+/]此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ALT+/]快捷键带来的好处吧. 2. ...