-我生君未生,君生我已老。 我離君天涯,君隔我海角。
-就像這首詩一樣,WCF是個什么動動我也是從零開始學習,這篇文章主要是介紹如何實現一個WCF的示例,更多是告訴大家怎么做而非為什么這么做。深層次的問題,我們后面再深究。
話說WCF(Windows Communication Foundation)由微軟發展的一組數據通信的應用程序開發接口。它為面向服務(Service Oriented)應用程序提供一個分布式編程框架,在.NET3.0引入,可以說是集分布式應用程序開發之大乘者。
為什么這么說呢,如果是.NET2.0和之前的版本,微軟發展了Web Service,.NET Remoting,以及基礎的 Winsock 等通信方法。而且每個通信方法的設計方法不同並且相互有重疊,例如 .NET Remoting 可以開發 SOAP, HTTP 通信。自然每一個通信方法都是要從新學習的,這就對像我這樣被微軟慣壞了的程序猿灰常的不友善了。
大幸的是,微軟重新查看了這些通信方法,並設計了一個統一的程序開發模型,對於數據通信提供了最基本最有彈性的支持,這就是 Windows Communication Foundation。
PS:請大家不要鄙視我是因為想一勞永逸才學WCF=。=
------------------------------------約會開始-----------------------------------
今天我們的目的是牽手成功,為了夠拉風,我們需要VS2008安裝NET 3.0以上版本(這樣才能創建WCF應用程序模板),不夠拉風妹子不出門,你們懂的。
首先我們新建一個WCF服務應用程序,如果你的座駕夠拉風,就會在如圖1所示的地方找到WCF服務應用程序的模板。
圖1
圖2
完成之后呢,VS已經創建了一個WCF服務應用程序,並且提供給我們了一個簡單的示例代碼。結構如圖2所示。
沒有上述環境的同學,還有一種創建WCF服務應用程序的方法,需要分別創建4個項目來定義服務契約(Contracts),實現服務契約(Services),提供宿主(Hosting)和客戶端(Client)。
這種方式在Artech的WCF之旅的第一篇有詳述,我就不畫蛇添足了。
IService1.cs:定義服務契約。VS生成的示例代碼如下:

// 注意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的接口名“IService1”。 [ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); // TODO: 在此添加您的服務操作 } // 使用下面示例中說明的數據約定將復合類型添加到服務操作。 [DataContract] public class CompositeType { bool boolValue = true; string stringValue = "Hello "; [DataMember] public bool BoolValue { get { return boolValue; } set { boolValue = value; } } [DataMember] public string StringValue { get { return stringValue; } set { stringValue = value; } } }
我們可以看到IService1是一個接口,由特性[ServiceContract]來指示這個接口在應用程序中用來定義服務契約。
接口中的方法使用[OperationContract]特性來指示這個方法是服務契約的一個部份,可供遠程調用。
CompositeType類是服務端和客戶端之間要傳送的自定義數據類型,使用[DataContract]特性來指示該類的示例對象可以被序列化在服務端和客戶端之間傳送。
但成員方法不會被傳遞。並且默認情況下除非使用[DataMember]特性來指示,不具有該特性的成員都被排除在外,也就是說,客戶端程序不會獲得被排除在外的成員的任何信息。
有人看到這肯定會喊,樓主是想拿VS生成的東西當示例?當然,我沒准備學騰訊,既然我們是來牽手的,就寫個牽手的例子把。
來修改一下服務契約,命名空間為JohnConnor.TakeYourHand
[ServiceContract] public interface ITakeYourHand { [OperationContract] Result FirstLook();//獲取第一眼印象分 [OperationContract] Result ShowTime();//嘗試表現下自己 [OperationContract] Result TakeHand(int Point);//嘗試牽手 } [DataContract] public class Result { [DataMember] public int Score { get; set; } [DataMember] public bool Succeed { get; set; } [DataMember] public string Message { get; set; } }
ITakeYourHand接口定義了我們這個牽手服務程序的服務契約,Result則定義了一個數據協議,它可以作為客戶端和服務端傳遞數據的載體。
Server1.svc:實現服務契約,當然這個文件還有一個特殊的用途:對WCF服務的調用就體現在對.svc文件的訪問上,它本身還載有其他一些服務的屬性信息(這個有木有人賜教一下?)。
現在我們把之前定義的接口在Server1.svc.cs里實現一下。命名空間不變。
public class TakeYourHand : ITakeYourHand { public Result FirstLook() { Random num = new Random(); Result result = new Result() { Score = num.Next(0, 10),//返回一個1~9的隨機人品 Succeed = false }; result.Message = "第一印象" + result.Score + ",Good Luck!"; return result; } public Result TakeHand(int Point) { Random num = new Random(); Result result = new Result(); if (num.Next(Point, 11) == 10)//分數越大,成功幾率越大 { result.Succeed = true; result.Score = 0; result.Message = "木有反抗,恭喜恭喜!"; } else { result.Succeed = false;//貿然牽手扣3分 result.Score = -3; result.Message = "心太急有木有,扣3分!"; } return result; } public Result ShowTime() { Random num = new Random();//隨機的表現大於2則Good否則Bad, Result result = new Result(); if (num.Next(0, 10)>2) { result.Score = 1; result.Message = "帥氣的表現征服了全場!加1分"; } else { result.Score = -1; result.Message = "扣鼻shi被妹子看見了!扣1分"; } result.Succeed = false; return result; } }
現在服務端已經大功告成拉。現在我們可以在解決方案資源管理器里選中Service1.svc,然后F5運行。
圖3
如圖3就會有一個Wcf測試客戶端彈出來,服務添加成功后在瀏覽器輸入顯示的地址,
這里是http://localhost:5140/Service1.svc 就可以看到一些關於服務的信息了,這時候服務就是開啟狀態了。
這里得提一下WCF的核心ABC了,
- A:Address Where-WCF的Service都有一個唯一的地址。這個地址給出了Service的地址和傳輸協議(Transport Protocol)
- B:Binding How-通信(Communication)的方式
- C:Contract What-契約,描述了Service能提供的各種服務
上圖中點擊一下配置文件就可以看到:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding> <!--省略綁定的細節--> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:5140/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITakeYourHand" contract="ITakeYourHand" name="BasicHttpBinding_ITakeYourHand" /> </client> </system.serviceModel> </configuration>
endpoint標簽里就描述了這三要素,地址address,綁定binding,契約contract。WCFbinding可以配置成BasicHttpBinding來兼容(或者說變身成)WebService。
下面我們繼續來進行客戶端的部份。演示如何來調用WCF服務。首先,我們來建一個控制台應用程序命名為JohnConnor.TakeYourHand.Client
首先必須保證服務在開啟狀態,然后右鍵添加服務引用,會彈出如圖4的會話框:
圖4 在地址欄中輸入WCF客戶測試端顯示的地址並前往,就能看到服務的詳細信息了。我們把命名空間改為
TakeYourHandService。確定,然后VS就會給我們生成一個服務引用和一個本地的app.config配置文件。
這時候 遠程對象 就應該存在於JohnConnor.TakeYourHand.Client.TakeYourHandService命名空間之下了。首先我們把這個命名空間引用到Program頭中。再來實現客戶端:
class Program { static void Main(string[] args) { int Point = 0; Console.WriteLine("約會開始,按回車鍵測試你的第一印象分!"); Console.ReadLine(); using (TakeYourHandClient client = new TakeYourHandClient())//創建一個遠程對象 { var result = client.FirstLook();//調用遠程方法FirstLook Point += result.Score; Console.WriteLine(result.Message); while (!result.Succeed && Point >= 0 && Point < 10) { Console.WriteLine("當前分數:" + Point.ToString() + ".輸入0嘗試牽手,輸入1來Show一下!回車確定"); var key = Console.ReadLine(); if (key == "0") { result = client.TakeHand(Point);//調用遠程方法TakeHand Point += result.Score; Console.WriteLine(result.Message); } if (key == "1") { result = client.ShowTime();//調用遠程方法TakeHand Point += result.Score; Console.WriteLine(result.Message); } else { Console.WriteLine("按規矩出牌,別亂來"); } } if (Point < 0) { Console.WriteLine("當前得分:" + Point.ToString()+",你被妹子甩了..."); } if (Point >= 10) { Console.WriteLine("妹子已主動牽起了你的手,恭喜恭喜!"); } Console.WriteLine("游戲結束"); Console.ReadKey(); } } }
TakeYourHandClient就是遠程對象了。因為我們實現契約的類名為TakeYourHand,所以遠程對象的命名一般是加Client作為后綴。在服務運行的時候,我們就可以調用遠程對象提供的方法來做一些事情了。運行控制台程序:
看來我還是個高富帥的得分,8分,兩下就讓妹子主動牽手了吼吼!不知道各位會不會是屌絲或是窮矮矬的得分。。。。
---------------------------------------------------分割線-------------------------------------------------
我也是剛開始接觸WCF,希望這個例子能幫助像我一樣的初學者對WCF有一個初步的印象。文中有任何問題,歡迎指正,一起進步。