<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      code4fun: one service,one config

      WCF的承載既可以通過編碼(Code)實現,也能夠通過配置(Config)實現.而且使用配置,更有利于日后的維護和擴展.WCF缺省的是將全部的服務配置都寫到一個config文件中去.這種方式更有利于專業的IT人員對服務進行集中式管理.在很多項目中,這種方式也能解決分工問題.但是它也有一定的弊端,比如: 一個無關緊要的service變動,就需要變動config,而對應用程序config的任何修改非常有可能導致應用程序的重啟或者異常.比如在網站中,如果更改web.config會導致Session,Application等的丟失.這些情況就會影響用戶的體驗.本文使用自定義ServiceHost的方式,實現一個Service對應一個config文件,這樣當有service發生修改的時候,管理人員就只需要更改對應的config文件。更好的實現了服務與服務之間的隔離。

      1)自定義配置文件的實現思路和關鍵點

      在ServiceHost的父類ServiceHostBase中,有一個和配置文件的加載密切相關的方法,它為:

      protected virtual void ApplyConfiguration();

      這個方法用于將應用程序配置文件中<system.serviceModel>節點下的配置信息,轉換成WCF的具體服務設置。那么重寫這個方法,應該就能實現上述目的。

      2)自定義配置文件的策略

      缺省的策略是服務與配置是多對一的關系,一個配置中包含全部的服務配置。那配置文件也就是默認的應用程序的配置文件了,在網站中是web.config,而在windows應用程序中,配置文件是應用程序名.config。而本文中要實現的自定義配置的策略是一個服務就對應一個配置文件,配置文件的名稱就是服務的全名。比如有一個服務名字為:Robin.Wcf.OnetoOne.Services.Calculator,那與其對應的服務配置文件名稱就是:Robin.Wcf.OnetoOne.Services.Calculator.config。同時還需要考慮這個文件的位置。我們制定一個策略:自定義的服務配置文件和缺省應用程序配置文件存放到同一個目錄。

      實現過程:

      第一步:創建一個解決方案,名稱為:Robin.Wcf.OnetoOne,并在其中添加三個項目,分別為:

      Robin.Wcf.OnetoOne.ServiceLib

      Robin.Wcf.OnetoOne.Services

      Robin.Wcf.OnetoOne.Services.Web

      這三個項目的作用分別為:

      Robin.Wcf.OnetoOne.ServiceLib中用于創建契約和實現服務,并且創建自定義的ServiceHost和自定義的ServiceHostFactory

      Robin.Wcf.OnetoOne.Services是對Robin.Wcf.OnetoOne.ServiceLib實現服務的一種自托管(self hosting),它最終是一個Console Application

      Robin.Wcf.OnetoOne.Services.Web是對Robin.Wcf.OnetoOne.ServiceLib實現服務的iis托管。

      第二步:實現服務

      在Robin.Wcf.OnetoOne.ServiceLib中創建兩個文件:ICalculator.cs和Calculator.cs,它們分別用于服務契約和服務實現,具體代碼如下:

      ICalculator.cs

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel;
      namespace Robin.Wcf.OnetoOne.Services
      {
      [ServiceContract]
      public interface ICalculator
      {
      [OperationContract]
      int Add(int a, int b);
      }
      }

      Calculator.cs

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      namespace Robin.Wcf.OnetoOne.Services
      {
      public class Calculator:ICalculator
      {
      public int Add(int a, int b)
      {
      return a + b;
      }
      }
      }

      實現的服務非常的簡單,因為我們的目的也不是要實現非常復雜的業務邏輯,而關鍵在于修改框架的使用方式上面。

      第三步:實現自定義的ServiceHost,名稱為:MyServiceHost。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel;
      using System.ServiceModel.Configuration;
      using System.Configuration;
      namespace Robin.Wcf.OnetoOne.Services
      {
      public class MyServiceHost:ServiceHost
      {
      public MyServiceHost(object singletonInstance, params Uri[] baseAddresses)
      : base(singletonInstance, baseAddresses)
      {
      }
      public MyServiceHost(Type serviceType, params Uri[] baseAddresses):base(serviceType,baseAddresses)
      {
      }
      /// <summary>
      /// override ApplyConfiguration to load config from custom file
      /// </summary>
      protected override void ApplyConfiguration()
      {
      //get custom config file name by our rule: config file name = ServiceType.Name
      var myConfigFileName = this.Description.ServiceType.FullName;
      //get config file path
      string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
      string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config");
      if (!System.IO.File.Exists(myConfigFilePath))
      {
      base.ApplyConfiguration();
      return;
      }
      var configFileMap = new System.Configuration.ExeConfigurationFileMap();
      configFileMap.ExeConfigFilename = myConfigFilePath;
      var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
      var serviceModel = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);
      if (serviceModel == null)
      {
      base.ApplyConfiguration();
      return;
      }
      foreach (ServiceElement serviceElement in serviceModel.Services.Services)
      {
      if (serviceElement.Name == this.Description.ServiceType.FullName)
      {
      LoadConfigurationSection(serviceElement);
      return;
      }
      }
      throw new Exception("there is no service element match the description!");
      }
      }
      }

      在自定義的ServiceHost中,主要是通過重寫(override)ApplyConfiguration方法來實現,將服務的全名,也就是this.Description.ServiceType.FullName作為配置文件的文件名,然后仍然使用.config作為后綴。使用缺省應用程序配置文件的路徑作為自定義配置文件路徑,缺省的配置文件路徑的獲取方法是:

      string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
      下面涉及到一個難題,如何將自定義文件作為系統配置文件,下面的代碼段解決了這個問題:
      var configFileMap = new System.Configuration.ExeConfigurationFileMap();
      configFileMap.ExeConfigFilename = myConfigFilePath;
      var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
      最后得到的config是System.Configuration.Configuration類別的一個實例。
      將自定義的文件作為配置并生成配置對象后,接下來要做的就是在此Configuration對象中尋找ServiceModeSectionGroup,然后通過在ServiceModeSectionGroup中獲取
      和當前要承載的服務名稱相等的ServiceElement,方法如下面的代碼所示:
      var serviceModel = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);
      if (serviceModel == null)
      {
      base.ApplyConfiguration();
      return;
      }
      foreach (ServiceElement serviceElement in serviceModel.Services.Services)
      {
      if (serviceElement.Name == this.Description.ServiceType.FullName)
      {
      LoadConfigurationSection(serviceElement);
      return;
      }
      }
      throw new Exception("there is no service element match the description!");

      最后,如果在配置中找不到與承載服務匹配的節點,就拋出異常。

      第四步:實現自定義的ServcieHostFactory:MyServiceHostFactory

      如果承載單純是Consol Application或者其他非Web應用程序,實現了第三步就可以了。但在Web的.svc中,沒有顯示的指定ServiceHost的Factory,那它在默認情況下是使用ServiceHostFactory的,而ServiceHostFactory產生的是ServiceHost對象,想要使用我們上一步中自定義的MyServiceHost,需要實現一個自定義的ServcieHostFactory,實現代碼非常簡單:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Activation;
      using System.ServiceModel;
      using System.Reflection;
      namespace Robin.Wcf.OnetoOne.Services
      {
      public class MyServiceHostFactory:ServiceHostFactory
      {
      protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
      {
      return  new MyServiceHost(serviceType, baseAddresses);
      }
      }
      }

      其實,就是在CreateServiceHost方法中返回一個MyServiceHost就可以了。

      第五步:實現Console的承載

      在Robin.Wcf.OnetoOne.Services中,新建一個config文件,名稱為:Robin.Wcf.OnetoOne.Services.Calculator.config,注意名稱和已經實現的服務的全名稱一致。將其內容設置為:

       

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
      <system.serviceModel>
      <services>
      <service name="Robin.Wcf.OnetoOne.Services.Calculator">
      <host>
      <baseAddresses>
      <add baseAddress="http://127.0.0.1:5698"/>
      </baseAddresses>
      </host>
      <endpoint address="Calculator" binding="wsHttpBinding" contract="Robin.Wcf.OnetoOne.Services.ICalculator"></endpoint>
      </service>
      </services>
      </system.serviceModel>
      </configuration>

      注意了,自定義的配置文件也是配置文件,它也需要和缺省應用程序的配置文件格式一致,首先要有<configuration> 節點。

      然后,設置Programe.cs的代碼為:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      namespace Robin.Wcf.OnetoOne.Services
      {
      public class Programe
      {
      static void Main(string[] args)
      {
      using(MyServiceHost host = new MyServiceHost(typeof(Calculator)))
      {
      host.Opened+=new EventHandler(delegate(object sender,EventArgs e){
      Console.WriteLine("Service is Opened!");
      foreach (var channelDiapacher in host.ChannelDispatchers)
      {
      Console.WriteLine("listen url:" + channelDiapacher.Listener.Uri.ToString());
      }
      });
      host.Open();
      }
      Console.Read();
      }
      }
      }

      第六步:實現IIS承載

      在Robin.Wcf.OnetoOne.Services.Web中,首先引用Robin.Wcf.OnetoOne.ServiceLib,然后同樣添加一個自定義配置文件:Robin.Wcf.OnetoOne.Services.Calculator.config。代碼為:

       

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
      <system.serviceModel>
      <services>
      <service name="Robin.Wcf.OnetoOne.Services.Calculator" behaviorConfiguration="Robin.Wcf.OnetoOne.WebHost.Service1Behavior">
      <endpoint binding="wsHttpBinding" contract="Robin.Wcf.OnetoOne.Services.ICalculator"></endpoint>
      </service>
      </services>
      <behaviors>
      <serviceBehaviors>
      <behavior name="Robin.Wcf.OnetoOne.WebHost.Service1Behavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
      </serviceBehaviors>
      </behaviors>
      </system.serviceModel>
      </configuration>

      將Service.svc的代碼更改為:

      <%@ ServiceHost Language="C#" Debug="true" Service="Robin.Wcf.OnetoOne.Services.Calculator"
      Factory="Robin.Wcf.OnetoOne.Services.MyServiceHostFactory" %>
      
      

      注意Service與Factory的配置。

       

      接下來的一步就是驗證我們的實現是否可行了,啟動Robin.Wcf.OnetoOne.Services,得到如下的程序輸出:

      image

      結合上面的代碼我們可以發現,配置在Robin.Wcf.OnetoOne.Services.Calculator.config中的配置已經起到了預期的效果。說明在Console中可行

       

      下面啟動Robin.Wcf.OnetoOne.Services.Web中的Service.svc,能得到如下的輸出結果:

      image

      表明,在iis的承載中也工作正常。

       

      參考資料:

      Custom Config file for a WCF Service hosted in IIS   

       

      示例代碼:https://files.cnblogs.com/jillzhang/Robin.Wcf.OnetoOne.rar

       

      Next Topic : One Host,Many Service!

      posted @ 2008-11-02 22:42  Robin Zhang  閱讀(4283)  評論(9)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品国产精品不乱码| 四虎永久精品免费视频| 中牟县| 国产不卡的一区二区三区| 亚洲国产精品区一区二区| 国产精品免费AⅤ片在线观看| 日韩乱码人妻无码中文字幕视频| 亚洲五月天一区二区三区| 国产乱子伦视频在线播放| 无码av中文字幕免费放| 国产中文三级全黄| 亚洲乱色一区二区三区丝袜| 亚洲天堂av 在线| 亚洲av无码乱码在线观看野外| 热久久美女精品天天吊色| 成人无码潮喷在线观看| 成年女人免费v片| 麻豆一区二区三区蜜桃免费| 亚洲av成人在线一区| 日本无遮挡真人祼交视频| 婷婷五月综合激情| 国产视频精品一区 日本| 国产美女69视频免费观看| 樱桃视频影院在线播放| 一级女性全黄久久生活片| 亚洲精品成人区在线观看| 爱性久久久久久久久| 欧美成人aaa片一区国产精品| 国产三级精品三级在线看| 成人做受120秒试看试看视频| 狠狠色噜噜狠狠狠狠av不卡| 免费A级毛片中文字幕| 杭锦后旗| 人人妻人人做人人爽夜欢视频| 日韩人妻系列无码专区| 国产99青青成人A在线| 精品无码老熟妇magnet| 97人人添人人澡人人澡人人澡| 欧美交a欧美精品喷水| 亚洲综合91社区精品福利| 国产高清不卡视频|