官术网_书友最值得收藏!

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)該方法。

主站蜘蛛池模板: 改则县| 景东| 临洮县| 容城县| 奈曼旗| 镇安县| 鞍山市| 方正县| 神池县| 会泽县| 封开县| 阳东县| 钟祥市| 涟水县| 基隆市| 临清市| 清徐县| 桑日县| 荆州市| 新疆| 天门市| 九江县| 潮州市| 隆昌县| 布尔津县| 剑河县| 迭部县| 营口市| 海城市| 朔州市| 会昌县| 余干县| 九龙县| 万州区| 三原县| 永平县| 滕州市| 亳州市| 潜山县| 平舆县| 五河县|