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生成了。

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text; namespace WcfServiceLibrary
{
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
} public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
}

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

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

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

namespace WcfService_HostConsole
{
class Program
{
static void Main(string[] args)
{
try
{
ServiceHost serviceHost = new ServiceHost(typeof(Service1));
if (serviceHost.State != CommunicationState.Opened)
{
serviceHost.Open();
} Console.WriteLine("WCF 服务正在运行......");
Console.WriteLine("输入回车键 <ENTER> 退出WCF服务");
Console.ReadLine();
serviceHost.Close(); }
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}

4、 WCF服务的Winform程序寄宿

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

namespace WcfService_HostWinform
{
public partial class FrmMain : Form
{
ServiceHost serviceHost = null;
BackgroundWorker worker = null; public FrmMain()
{
InitializeComponent(); worker = new BackgroundWorker();
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork += new DoWorkEventHandler(worker_DoWork); if (!worker.IsBusy)
{
tssTips.Text = "正在启动......";
lblTips.Text = tssTips.Text;
worker.RunWorkerAsync();
}
} void worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
serviceHost = new ServiceHost(typeof(Service1));
if (serviceHost.State != CommunicationState.Opened)
{
serviceHost.Open();
} e.Result = "正常";
}
catch (Exception ex)
{
e.Result = ex.Message;
}
} void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result != null)
{
if (e.Result.ToString() == "正常")
{
tssTips.Text = "服务正在进行侦听......";
}
else
{
tssTips.Text = string.Format("错误:{0}", e.Result);
} lblTips.Text = tssTips.Text;
}
}
...........................
}
}

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

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

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

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

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

    public class ServiceManager : ServiceBase
{
private static object syncRoot = new Object();//同步锁
private ServiceHost serviceHost = null; //寄宿服务对象 public ServiceManager()
{
this.ServiceName = Constants.ServiceName;
} /// <summary>
/// 设置具体的操作,以便服务可以执行它的工作。
/// </summary>
protected override void OnStart(string[] args)
{
try
{
serviceHost = new ServiceHost(typeof(Service1));
if (serviceHost.State != CommunicationState.Opened)
{
serviceHost.Open();
}
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
} LogTextHelper.Info(Constants.ServiceName + DateTime.Now.ToShortTimeString() + "已成功调用了服务一次。"); LogTextHelper.Info(Constants.ServiceName + "已成功启动。");
}

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

        /// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
ServiceController service = new ServiceController(Constants.ServiceName); // 运行服务
if (args.Length == 0)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new ServiceManager() };
ServiceBase.Run(ServicesToRun);
}
else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i")
{
#region 安装服务
if (!ServiceIsExisted(Constants.ServiceName))
{
try
{
string[] cmdline = { };
string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller();
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
transactedInstaller.Installers.Add(assemblyInstaller);
transactedInstaller.Install(new System.Collections.Hashtable()); TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10);
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch (Exception ex)
{
LogTextHelper.Info(ex);
throw;
}
}
#endregion
}
else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u")
{
#region 删除服务
try
{
if (ServiceIsExisted(Constants.ServiceName))
{
string[] cmdline = { };
string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller();
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
transactedInstaller.Installers.Add(assemblyInstaller);
transactedInstaller.Uninstall(null);
}
}
catch (Exception ex)
{
LogTextHelper.Info(ex);
throw;
}
#endregion
}
}

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

安装脚本

"WcfService_HostWinService.exe" -i
pause

卸载脚本

"WcfService_HostWinService.exe" -u
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)])。

namespace WcfServiceForWinform
{
[ServiceContract]
public interface IService1
{
[OperationContract]
void DoWork(); [OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
string GetData(int value);
}
}

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

namespace WcfServiceForWinform
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public void DoWork()
{
} public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
}

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

<?xml version="1.0"?>
<configuration> <system.web>
<compilation debug="true"/>
</system.web> <system.serviceModel>
<services>
<service name="WcfServiceForWinform.Service1" behaviorConfiguration="ServiceConfig">
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJsonP" behaviorConfiguration="webHttpBehavior"
contract="WcfServiceForWinform.IService1">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9000/Service1/" />
</baseAddresses>
</host>
</service>
</services> <bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings> <behaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors> <serviceBehaviors>
<behavior name="ServiceConfig">
<serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</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. SQL分组查询group by

    注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里. 1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用 group ...

  2. python中的类简单讲解

    类似其它的语言, Python 中的函数使用小括号( () )调用.函数在调用之前必须先定义.如果函数中没有 return 语句, 就会自动返回 None 对象.      Python 是通过引用调 ...

  3. 第二篇 顾问实施ERP与医生看病过程类比

    我从08年开始涉足企业信息化咨询行业.当时做的第一个项目是汕头某黄金珠宝公司的SAP ERP业务优化项目.我在项目上担任顾问助理的角色.我们公司的老板据说是以前ORACLE公司华南区的总监,后来是格兰 ...

  4. [NYIST737]石子合并(一)(区间dp)

    题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737 很经典的区间dp,发现没有写过题解.最近被hihocoder上几道比赛题难住了 ...

  5. tomcat启动时报:IOException while loading persisted sessions: java.io.EOFException的解决方案

    错误代码如下: 严重: IOException while loading persisted sessions: java.io.EOFException java.io.EOFException ...

  6. 51nod1757 大灾变

    能想到二分答案+最大流判断是否符合.但是不知道如何建图qaq.参考的是http://blog.csdn.net/fsss_7/article/details/52132046的建图方法 #includ ...

  7. Linux mv 命令的10个实用例子

    当你想要将文件从一个位置移动到另一个地方并且不想复制它,那么mv 命令是完成这个任务的首选.本文中总结了十个Linux mv 命令的实例,希望能给大家带来一些帮助. 初识 mv 命令 mv 命令是一个 ...

  8. JavaScript——new Date().getMonth()

    new Date().getMonth(); 说明:参照现在的月份,getMonth()返回的是0-11的数字,也就是说0=1月,1=2月……11=12月 当前的月份就是,new Date().get ...

  9. UISlide

    UISlide属性   1.   minimumValue  : 当值可以改变时,滑块可以滑动到最小位置的值,默认为0.0 _slider.minimumValue = 10.0; 2.   maxi ...

  10. 15.Object-C--浅谈Foundation框架OC数组NSArray与NSMutableArray

    昨天总结了一下NSString与NSMutableString,今天我在这里总结一下NSArray与NSMutableArray. NSArray数组是:不可变数组. nil 是数组元素结束的标记.O ...