這篇隨筆寫了一段時間了,當時沒有發布,今天整理文檔的時候發現了,順便給配了些圖。主要是紹了一下WCF編程模型,並給了一個簡單的示例。
概述
WCF框架是下一代.NET平台通信應用程序的核心。它包含了Web服務、Remoting、同步和異步消息應用程序的開發,合並了所有最近有關的各種標准,建立了通過XML配置文件替代C#代碼(如果你喜歡的話可以繼續使用代碼)對服務定義進行配置的模型。
WCF的設計思路是使開發者可以專注於開發所需的業務邏輯而不是增加工作(服務器和客戶端之間的通信、數據傳輸等),WCF將為你處理這些問題,並且通過使用擴展的配置文件讓一切變得更加容易實現。
WCF程序結構
一個完整的WCF解決方案包括如下四個部分:
-
契約(Contracts): 主要定義了實現那些服務,如何訪問服務
-
服務(Services): 實現契約定義的方法
-
宿主程序(Hosting): 提供低層傳輸功能的支持
-
客戶端(Client): 根據契約訪問服務
下面我們就來逐一講解如何實現一個簡單的WCF程序。
實現契約和服務
契約通常是一個接口,定義了我們會提供哪些服務。以一個簡單的計算器為例,假如我們要提供一個加減法的服務,則定義接口如下:
public interface Icalculator
{
double Add(double x, double y);
double Subtract(double x, double y);
}
而服務則是如何實現這個契約,對於上述接口,實現方式如下:
public class CalculatorService : Icalculator
{
public double Add(double x, double y)
{
return x + y;
}
public double Subtract(double x, double y)
{
return x - y;
}
}
對契約和服務有了基本了解后,我們就可以在WCF程序中實現它了,我們通常把契約和服務放在一個類庫項目中實現,首先新建一個WCF服務庫項目(也可以新建一個類庫項目,然后添加System.ServiceModel.dll的引用):
使用WCF服務庫項目模板創建項目后,發現系統會自動提供了一個簡單的契約和服務的實現,在這里我們將其替換成前面定義的接口和實現。
首先把契約文件IService1.cs替換成我們的接口:
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double x, double y);
[OperationContract]
double Subtract(double x, double y);
}
可以看到,和前面定義的基本接口有點區別的是:
-
接口名稱上加了 ServiceContract 屬性
-
接口方法上加了 OperationContract 屬性
這個是告訴WCF宿主程序定義的契約名稱和要實現的接口,否則WCF宿主程序也無法知道該如何加載服務。實現服務的代碼和前面一樣,這里就不列出來了。
實現完我們的服務和契約后,按Ctrl+F5后就可以直接測試了。雖然我們沒有編寫客戶端,但系統自動提供了一個WcfTestClient供使用的:
關於WCF測試客戶端的更多信息,可以參看MSDN文章:啟用WCF測試客戶端(WCF Test Client)的相關技巧。
實現宿主程序
前面我們可以看到,編寫WCF服務端程序時,雖然我們並沒有實現宿主程序,但在客戶端仍然能夠訪問服務。這是因為在測試Wcf庫的時候,系統自動啟動了一個宿主程序WcfSvcHost.exe,並加載了該服務,以便我們能測試訪問。不過WcfSvcHost.exe只是一個輕量級的宿主程序,主要用於測試用,對於實際項目,我們可以把它部署到IIS中,都可以不用編寫自己的宿主程序。
除了IIS外,我們也可以編寫自己的宿主程序,通過一個控制台或窗口程序來實現宿主程序,這樣也可以在沒有IIS的機器上運行我們的服務,也可以更改低層傳輸協議,從而獲取更高的傳輸效率等。
實現宿主程序也比較簡單,首先創建一個控制台項目,然后添加System.ServiceModel.dll和前面定義的服務項目WcfService的引用,然后就可以實現宿主程序了:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(CalculatorService));
host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://localhost:8733/Design_Time_Addresses/WcfService/Service1/");
if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://localhost:8733/Design_Time_Addresses/WcfService/Service1/wsdl");
host.Description.Behaviors.Add(behavior);
}
host.Open();
Console.WriteLine("CalculaorService已經啟動,按任意鍵終止服務!");
Console.Read();
host.Close();
}
這里的大部分都是配置操作,這個配置對新手來說非常多,寫在代碼里也不好看,因此通常是寫在App.Config中,我這里是直接把WcfService工程中<system.serviceModel>節直接拷貝過來的。要修改這個配置,可以使用VisualStudio中的WCF服務配置編輯器。
把配置挪到App.Config中后,代碼可以簡化如下:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(CalculatorService));
host.Open();
Console.WriteLine("CalculaorService已經啟動,按任意鍵終止服務!");
Console.Read();
host.Close();
}
從代碼中可以看到,我們只需要創建一個ServiceHost對象,然后調用Open方法開啟服務即可,並不需要什么額外的操作,非常簡單。
實現客戶端
要實現客戶端,我們需要知道如下兩個信息:
-
服務端提供了那些服務
-
該如何采取這些方式訪問服務
這個信息可以通過宿主程序發布的wsdl獲取,客戶端無需知道服務區的實現細節,直接根據wsdl地址即可。例如,對於前面的例子中,我的服務地址是:http://localhost:8733/Design_Time_Addresses/WcfService/Service1/(在App.config中配置的),直接通過瀏覽器可以wsdl的發布地址,並能獲取相關信息。
有了該信息后,借助VisualStudio的強大功能就可以非常快捷的實現客戶端程序了。我們首先插件一個控制台程序,然后添加web服務引用:
添加該服務后,和WebService一樣,系統自動生成了Client類。
借助這個Client類,就可以訪問前面的服務了。
static void Main(string[] args)
{
using (var proxy = new CalculatorClient())
{
Console.WriteLine("{0} + {1} = {2}", 3, 5, proxy.Add(3, 5));
Console.WriteLine("{0} - {1} = {2}", 3, 5, proxy.Subtract(3, 5));
}
}
實際上,根據服務端發布的wsdl信息,也可以使用java等其它語言編寫,是一種非常靈活的方式。
小結
從本文中的這個例子可以看出,WCF非常好的上屏蔽了低層細節(服務器和客戶端之間的通信、數據傳輸等),開發者只需要關注業務邏輯即可,並且非常靈活,是一門非常優秀的RMI技術。
關於WCF園子里有許多文章,這些都是非常好的學習材料,我目前也只是處於管中窺豹的階段,后續有空再寫寫相關文章。
- 我的WCF之旅(1):創建一個簡單的WCF程序
- 我的WCF之旅(2):Endpoint Overview
- 我的WCF之旅(3):在WCF中實現雙向通信(Bi-directional Communication)
- 我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
- 我的WCF之旅(4):WCF中的序列化(Serialization)- Part II
- 我的WCF之旅(5):Service Contract中的重載(Overloading)
- 我的WCF之旅(6):在Winform Application中調用Duplex Service出現TimeoutException的原因和解決方案
- 我的WCF之旅(7):面向服務架構(SOA)和面向對象編程(OOP)的結合——如何實現Service Contract的繼承
- 我的WCF之旅(8):WCF中的Session和Instancing Management
- 我的WCF之旅(9):如何在WCF中使用tcpTrace來進行Soap Trace
- 我的WCF之旅(10): 如何在WCF進行Exception Handling
- 我的WCF之旅(11):再談WCF的雙向通訊-基於Http的雙向通訊 V.S. 基於TCP的雙向通訊
- 我的WCF之旅(12):使用MSMQ進行Reliable Messaging
- 我的WCF之旅(13):創建基於MSMQ的Responsive Service