昨天終於下定決心計划這個月要把WCF學完,之所以安排一個月的時間,我不要只是學些表面的東西,我要比較深入的去學習下它。如果只學些表面的東西,我想一般的人花個一周的時間就夠了。最近一段時間想要學的東西感覺太多了,想學習下Silverlight、WPF、WCF、MVC等,但總感覺好像很忙似的,我也不知道我在忙些什么,就這樣稀里糊塗的一天就過去,一事無成。昨天晚上終於想起了5月份寫的一個計划規則,還是按照這個計划規則去寫每天的計划、日記、月計划。這樣每天做了些什么,每天應該做些什么,目標很明確,再也不會像以前那樣,想學Silverlight、WPF、WCF、MVC等,一會兒想看下Silverlight,一會兒想看下WPF,一會兒想等找到份工作再去學習它們。像這樣下去這些東西的皮毛都沒有學到,而且這樣又把自己累得要死。 人們總喜歡說計划趕不變化,我覺得這沒有什么道理,我覺得只要你計划的合理的話,這個計划肯定不會難產的。這是我最近的狀況總結。費話說的有點多了,還大家見諒。。。呵呵!下面主要是和大家分享下我今天所學的雙工模式。
這個其實不難,但讓我花比較長的時間,咱天生有點愚笨,沒辦法,所以特意記錄下,以免下次又忘記了。
雙工模式的特點是:無論使用單向消息發送還是請求/答復消息發送方式,服務和客戶端均能夠獨立地向對方發送消息。對於必須直接與客戶端通信或向消息交換的任意一方提供異步體驗(包括類似於事件的行為)的服務來說,這種雙向通信形式非常有用。
由於存在與客戶端通信的附加機制,雙工模式比請求/答復或單向模式要略為復雜。
若要設計為雙工協定,還必須設計回調協定,並將該回調協定的類型分配給標記服務協定的ServiceContractAttribute屬性(attribute)的CallbackContract屬性(protery)。
若要實現雙工模式,您必須創建第二個接口,該接口包含在客戶端調用的方法聲明。(以上四段話摘自:MSDN Webcasts 徐長龍講的《跟我一起從零開始學WCF系列課程》的第二章,希望大家能充分理解這四段的意思,我今花了比較長的時間來學這個雙工模式,就是因為沒有注意看這四段話,沒有理解好。)。
下面我們就來創建一個WCF項目吧!
點擊確定,就這樣創建了一個WCF項目了。簡單吧。。。
目錄如下:
你把IService1.cs和Serivce1.cs刪除了也可以,沒事的,咱就懶得刪除了。咱把IService1.cs和Serivce1.cs里面的內容全部刪除了。以下是IService1.cs文件里的內容:
namespace WcfServiceLibrary4 { [ServiceContract(Namespace = "http://Microsoft.ServiceMode.Samples", SessionMode = SessionMode.Required, CallbackContract = typeof(IB))] //定義一個服務接口 public interface IA { [OperationContract(IsOneWay=true)] void Clear(); } //這個是服務端調用客戶端里方法的一個接口,在客戶端里寫一個類繼承這個接口時,你是找到不IB這個接口的名字的,上面的CallbackContract = typeof(IB)這句話指定的回調的接口是IB,但它是以IACallback的形式出現的 public interface IB { [OperationContract(IsOneWay=true)] void E(double e); } }
以下是Serivce1.cs里面的代碼:
namespace WcfServiceLibrary4 { [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class A : IA { double result; //聲明一個IB接口的對象 IB ib = null; //A類的構造方法 public A() { result = 0.0D; //實例化一個IB ib = OperationContext.Current.GetCallbackChannel<IB>(); } public void Clear() { //服務端調用客戶端的E方法 ib.E(result + 9); } } }
然后把App.config配置文件修改下就可以了。
本來是這樣的:
<service name="WcfServiceLibrary4.Service1" behaviorConfiguration="WcfServiceLibrary4.Service1Behavior"> <host> <baseAddresses> <add baseAddress = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary4/Service1/" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- 除非完全限定,否則地址將與上面提供的基址相關 --> <endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary4.IService1">
修改后:
<service name="WcfServiceLibrary4.A" behaviorConfiguration="WcfServiceLibrary4.Service1Behavior"> <host> <baseAddresses> <add baseAddress = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary4/A/" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- 除非完全限定,否則地址將與上面提供的基址相關 --> <endpoint address ="" binding="wsDualHttpBinding" contract="WcfServiceLibrary3.IA">
一定要把wsHttpBinding改成wsDualHttpBinding,請大家仔細對照下。
下面實現客戶端的調用吧,不過端還得實現服務端IB的接口。
我在這個項目里添加了個命令項目,你添加個WebFrom項目或者Windows項目也可以的。
哦,差點忘了應該先生成下服務,然后再在命令項目里右擊“引用”選擇“添加服務引用",不要點錯了哦。
然后我們開始在Program.cs里添加如下代碼:
//請記得添加以下兩個命名空間 using System.ServiceModel; using ConsoleApplication1.ServiceReference1; namespace ConsoleApplication1 { /// <summary> /// 我今天主要是在B繼承一個接口這個花了很長的時間,我總以為能找到服務端里的IB接口,誰知道服務端的接口IB是IACallback的形式出現在客戶端 /// </summary> public class B:IACallback { #region IACallback 成員 //實現了IB接口的E方法 public void E(double e1) { Console.WriteLine("E:" + e1); }#endregion } class Program { static void Main(string[] args) { InstanceContext instanceContext = new InstanceContext(new B()); ServiceReference1.AClient client = new AClient(instanceContext); client.Clear(); Console.ReadKey(); } } }
歡迎大家拍磚,咱家正在建房......,如果你是燒磚廠的,歡迎你一車磚一車磚的拍,咱高興的很吶,時間也不早了,明天早上還要去面試,該洗洗睡了,晚安各位基友。。。