好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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接口,就是一种非常方便的调用了。

主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
  转载请注明出处:
撰写人:伍华聪   http://www.iqidi.com  
    

 

 

标签:  Winform开发框架

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于WCF的几种寄宿方式的详细内容...

  阅读:52次