我們可以通過代碼和配置文件的方式完成所有的服務寄宿工作。在Hosting項目中的Program.cs文件中的Main方法中,通過代碼實現對 BookService的WCF服務應用的寄宿實現。
第四步:通過自我寄宿的方式寄宿服務
WCF服務需要依存一個運行著的進程(宿主),服務寄宿就是為服務指定一個宿主的過程。WCF是一個基於消息的通信框架,採用基於終結點(Endpoint)的通信手段。
終結點主要由地址(Address)、綁定(Binding)和協定(Contract)三要素組成,如圖所示。由於三要素應為首字母分別為ABC,所以就有了易於記憶的公式:Endpoint = ABC。一個終結包含了實現通信所必需的所有信息。如下圖。
終結點三要素
- 地址(Address):一個指示可以查找終結點的位置的地址。地址決定了服務的位置,解決了服務定址的問題
- 綁定(Binding):一個指定客戶端如何與終結點進行通信的綁定。綁定實現了通信的所有細節,包括網路傳輸、消息編碼,以及其他為實現某種功能(比如安全、可靠傳輸、事務等)對消息進行的相應處理。WCF中具有一系列的系統定義綁定,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,
- 協定(Contract):一個標識可用操作的協定。協定是對服務操作的抽象,也是對消息交換模式以及消息結構的定義。
- 行為(Behavior):一組指定終結點的本地實現細節的行為。
服務寄宿的目的就是開啟一個進程,為WCF服務應用提供一個運行的環境。通過為服務添加一個或多個終結點,使之暴露給潛在的服務調用者。服務調用者最終通過相匹配的終結點對該服務進行調用。
一)代碼方式實現寄宿
我們可以通過代碼的方式完成所有的服務寄宿工作。在Hosting項目中的Program.cs文件中的Main方法中,通過代碼實現對 BookService的WCF服務應用的寄宿實現。具體代碼如下:
using SCF.WcfService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
namespace Hosting
{
class Program
{
// 無配置文件的啟動程式
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(BookService)))
{
host.AddServiceEndpoint(typeof(IBookService), new WSHttpBinding(),
"http://127.0.0.1:8888/BookService");
if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/BookService/metadata");
host.Description.Behaviors.Add(behavior);
}
host.Opened += delegate
{
Console.WriteLine("BookService,按任意鍵終止服務!");
};
host.Open();
Console.Read();
}
}
}
WCF服務寄宿通過一個特殊的對象完成:ServiceHost。在上面的代碼基本實現的功能說明,基於WCF服務應用的類型(typeof(BookService))創建了ServieHost對象,並添加了一個終結點。具體的地址為http://127.0.0.1:8888/BookService,採用了WSHttpBinding,並指定了服務協定的類型IBookService。
松耦合是SOA的一個基本的特征,WCF服務應用中客戶端和服務端的松耦合體現在客戶端只需要瞭解WCF服務基本的描述,而無需知道具體的實現細節,就可以實現正常的WCF服務調用。WCF服務的描述通過元數據(Metadata)的形式發佈出來。WCF中元數據的發佈通過一個特殊的服務行為ServiceMetadataBehavior實現。在上面提供的服務寄宿代碼中,我們為創建的ServiceHost添加了ServiceMetadataBehavior,並採用了基於HTTP-GET的元數據獲取方式,元數據的發佈地址通過ServiceMetadataBehavior的HttpGetUrl指定。在調用ServiceHost的Open方法對服務成功寄宿後,我們可以通過該地址獲取服務相關的元數據。
3) 運行已經生成的hosting.exe,然後在瀏覽器地址欄上鍵入http://127.0.0.1:8888/BookService/metadata,你將會得到以WSDL形式體現的服務元數據,如下圖所示。
通過HTTP-GET的方式獲取WCF服務的元數據
二)配置文件方式實現寄宿
在實際應用中,對於WCF應用服務的寄宿,一般不會直接通過編碼的方式進行終結點的添加和服務行為的定義,而是通過寫配置文件的方式實現,這樣可以方便修改。
1) 現在我在Hosting項目中添加一個app.config配置文件,把下麵的配置信息添加到配置文件app.config中。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8888/BookService/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadataBehavior" name="SCF.WcfService.BookService">
<endpoint address="http://127.0.0.1:8888/BookService"
binding="wsHttpBinding" bindingConfiguration="" contract="SCF.WcfService.IBookService" />
</service>
</services>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
2) 增加app.config配置文件與配置信息之後,我們原來寫的寄宿代碼就不能使用了,需要進行服務寄宿代碼的修改,而且代碼會變的更簡潔,只需幾行代碼就可以了。代碼如下。
static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(BookService)))
{
host.Opened += delegate
{
Console.WriteLine("BookService,使用配置文件,按任意鍵終止服務!");
};
host.Open();
Console.Read();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
3) 執行hosting.exe應用程式,結果如下圖。