- WCF技術(shù)剖析(卷1)
- 蔣金楠
- 1297字
- 2018-12-27 11:32:52
3.3.4 案例演示:如何自定義信道
WCF是一個(gè)極具擴(kuò)展性的通信框架,反映在信道層上就是可以自由地創(chuàng)建信道,利用這些自定義信道完成某項(xiàng)消息處理的功能。比如,可以通過自定義信道對消息進(jìn)行壓縮。
上述的3種消息交換模式中,請求-回復(fù)模式最為典型。在該模式下,消息發(fā)送端和接收端的信道分別實(shí)現(xiàn)了IRequstChannel和IReplyChannel接口。
本案例將演示如何自定義RequestChannel和ReplyChannel。在自定義信道的方法和屬性中,僅僅通過System.Console在控制臺上打印出方法或?qū)傩悦Q。這樣做的目的有兩個(gè),其一是為了簡單起見,因?yàn)楸景咐哪康脑谟谘菔拘诺朗侨绾巫远x的;其二就是當(dāng)我們把信道應(yīng)用于真正的WCF應(yīng)用時(shí),可以根據(jù)打印出來的類型指導(dǎo)具體執(zhí)行的方法和執(zhí)行的先后順序。為此先定義如下一個(gè)靜態(tài)的PrintHelper類,靜態(tài)Print方法打印出傳入實(shí)例的類型和方法(或者屬性名稱):
using System; namespace Artech.CustomChannels { public static class PrintHelper { public static void Print(object instance, string method) { Console.WriteLine("{0}.{1}", instance.GetType().Name, method); } } }
自定義RequestChannel
自定義請求信道SimpleRequestChannel實(shí)現(xiàn)IRequestChannel,并直接繼承自ChannelBase。
using System; using System.ServiceModel.Channels; using System.ServiceModel; namespace Artech.CustomChannels { public class SimpleRequestChannel.:ChannelBase,IRequestChannel { //方法成員 } }
信道并不能孤立地存在,它存在于一個(gè)由多個(gè)信道對象連接而成的信道棧中。所以,對于一個(gè)不處于棧尾的信道來說,在處理完消息后,一般會(huì)把處理后的消息傳遞給后一個(gè)信道。反映在方法實(shí)現(xiàn)上,需要在執(zhí)行本信道的某個(gè)方法之后,獲得下一個(gè)信道對象,調(diào)用同名的方法。所以在SimpleRequestChannel,我們需要定義一個(gè)特殊的字段成員:_innerChannel。該字段表示信道棧中的下一個(gè)信道,該字段在構(gòu)造函數(shù)中指定。在構(gòu)造函數(shù)中還須要指定一
個(gè)ChannelManagerBase對象,表示基于信道的信道工廠。
using System; using System.ServiceModel.Channels; using System.ServiceModel; namespace Artech.CustomChannels { public class SimpleRequestChannel.:ChannelBase,IRequestChannel { private IRequestChannel _innerChannel; public SimpleRequestChannel.(ChannelManagerBase channelManager, IRequestChannel innerChannel) : base(channelManager) { PrintHelper.Print(this, "SimpleRequestChannel."); this._innerChannel = innerChannel; } //其他成員 }
ChannelBase是一個(gè)抽象類,它定義一系列必須實(shí)現(xiàn)的protected抽象方法或?qū)傩裕▽?shí)際上這些受保護(hù)的抽象方法或?qū)傩远x在CommunicationObject中,ChannelBase繼承自CommunicationObject)。我們須要實(shí)現(xiàn)從基類繼承下來的一系列OnXxx、OnBeginXxx、OnEndXxx方法。
using System; using System.ServiceModel.Channels; using System.ServiceModel; namespace Artech.CustomChannels { public class SimpleRequestChannel.:ChannelBase,IRequestChannel { //其他成員 protected override void OnAbort() { PrintHelper.Print(this, "OnAbort"); this._innerChannel.Abort(); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "OnBeginClose"); return this._innerChannel.BeginClose(timeout,callback,state); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "OnBeginOpen"); return this._innerChannel.BeginOpen(timeout, callback, state); } protected override void OnClose(TimeSpan timeout) { PrintHelper.Print(this, "OnClose"); this._innerChannel.Close(timeout); } protected override void OnEndClose(IAsyncResult result) { PrintHelper.Print(this, "OnEndClose"); this._innerChannel.EndClose(result); } protected override void OnEndOpen(IAsyncResult result) { PrintHelper.Print(this, "OnEndOpen"); this._innerChannel.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { PrintHelper.Print(this, "OnOpen"); this._innerChannel.Open(timeout); } } }
SimpleRequestChannel實(shí)現(xiàn)了IRequestChannel接口,所以還須實(shí)現(xiàn)IRequestChannel所有的方法和屬性。
using System; using System.ServiceModel.Channels; using System.ServiceModel; namespace Artech.CustomChannels { public class SimpleRequestChannel.:ChannelBase,IRequestChannel { //其他成員 #region IRequestChannel Members public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "BeginRequest"); return this._innerChannel.BeginRequest(message,timeout, callback,state); } public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state) { PrintHelper.Print(this, "BeginRequest"); return this._innerChannel.BeginRequest(message, callback, state); } public Message EndRequest(IAsyncResult result) { PrintHelper.Print(this, "EndRequest"); return this._innerChannel.EndRequest(result); } public EndpointAddress RemoteAddress { get { PrintHelper.Print(this, "RemoteAddress"); return this._innerChannel.RemoteAddress; } } public Message Request(Message message, TimeSpan timeout) { PrintHelper.Print(this, "Request"); return this._innerChannel.Request(message,timeout); } public Message Request(Message message) { PrintHelper.Print(this, "Request"); return this._innerChannel.Request(message); } public Uri Via { get { PrintHelper.Print(this, "Via"); return this._innerChannel.Via; } } #endregion } }
自定義ReplyChannel
與SimpleRequestChannel類似,自定義的ReplyChannel(SimpleRequestChannel)繼承自ChannelBase,實(shí)現(xiàn)IReplyChannel接口,并以同樣的方式實(shí)現(xiàn)了從基類和接口中繼承的方法和屬性。
using System; using System.ServiceModel.Channels; namespace Artech.CustomChannels { public class SimpleReplyChannel:ChannelBase,IReplyChannel { private IReplyChannel _innerChannel; public SimpleReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel) : base(channelManager) { PrintHelper.Print(this, "SimpleReplyChannel"); this._innerChannel = innerChannel; } protected override void OnAbort() { PrintHelper.Print(this, "OnAbort"); this._innerChannel.Abort(); } public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "BeginReceiveRequest"); return this._innerChannel.BeginReceiveRequest(timeout, callback,state); } //其他成員 } }
自定義DuplexSessionChannel
為了演示自定義會(huì)話信道,我們創(chuàng)建一個(gè)繼承自ChannelBase并實(shí)現(xiàn)了IDuplexSessionChannel接口的自定義DuplexSessionChannel:SimpleDuplexSessionChannel。它的實(shí)現(xiàn)方式與自定義RequestChannel和ReplyChannel類似,不同的是innerChannel類型為IDuplexSessionChannel。
using System; using System.ServiceModel.Channels; using System.ServiceModel; namespace Artech.CustomChannels { public class SimpleDuplexSessionChannel:ChannelBase,IDuplexSessionChannel { private IDuplexSessionChannel _innerChannel; public SimpleDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel) : base(channelManager) { PrintHelper.Print(this, "SimpleDuplexSessionChannel"); this._innerChannel = innerChannel; } protected override void OnAbort() { PrintHelper.Print(this, "OnAbort"); this._innerChannel.Abort(); } //其他成員 public override T GetProperty<T>() { return this._innerChannel.GetProperty<T>(); } #endregion } }
SimpleDuplexSessionChannel除了實(shí)現(xiàn)從基類中繼承的抽象方法和屬性,以及定義在接口中的方法和屬性成員之外,還須要重寫GetProperty<T>()方法。該方法用于獲取信道某種類型的屬性,是探測信道是否具有某種功能和性能的手段。我們須要通過調(diào)用后續(xù)信道的同名方法來重新實(shí)現(xiàn)該方法。
- Visual FoxPro程序設(shè)計(jì)教程
- PHP程序設(shè)計(jì)(慕課版)
- Python自動(dòng)化運(yùn)維快速入門
- MATLAB應(yīng)用與實(shí)驗(yàn)教程
- 你必須知道的204個(gè)Visual C++開發(fā)問題
- Mastering Kali Linux for Web Penetration Testing
- Java EE核心技術(shù)與應(yīng)用
- OpenResty完全開發(fā)指南:構(gòu)建百萬級別并發(fā)的Web應(yīng)用
- Xcode 6 Essentials
- OpenCV 3 Blueprints
- jQuery從入門到精通(微課精編版)
- 大學(xué)計(jì)算機(jī)應(yīng)用基礎(chǔ)(Windows 7+Office 2010)(IC3)
- 你必須知道的.NET(第2版)
- 零基礎(chǔ)PHP從入門到精通
- Cinder:Begin Creative Coding