自定义信道基类

WCF是一个极具扩展性的通信框架 无论在服务模型层还是信道层 都具有很多扩展点 而信道层的扩展点主要体现在实现自定义信道以增强信道栈处理信息的能力 比如我们可以扩展信道层 实现一个自定义的信道 该信道提供一些方法将信息压缩 使信息的传输更快速 下面创建一个自定义的信道基类 实现当信道的某些方法执行时打印出该信道类型的名字和它方法的名字 接着调用下一个信道的方法 要实现自定义信道基类 可以使自定义信道基类派生于ChannelBase 因为ChannelBase是所有信道的基类 它通过实现各种接口IChannel、ICommunicationObject、IDefaultCommunicationTimeouts和继承CommunicationObjec类进而拥有信道最基本的操作方法

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public abstract class SimpleChannelBase : ChannelBase
  6. {
  7. protected void Print(string methodName)
  8. {
  9. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  10. }
  11. public ChannelBase InnerChannel { get; private set; }
  12. public SimpleChannelBase(ChannelManagerBase channelManager, ChannelBase innerChannel)
  13. : base(channelManager)
  14. {
  15. this.InnerChannel = innerChannel;
  16. }
  17.  
  18. protected override void OnAbort()
  19. {
  20. this.Print("OnAbort()");
  21. this.InnerChannel.Abort();
  22. }
  23.  
  24. protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  25. {
  26. this.Print("OnBeginClose()");
  27. return this.InnerChannel.BeginClose(timeout, callback, state);
  28. }
  29.  
  30. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  31. {
  32. this.Print("OnBeginOpen()");
  33. return this.InnerChannel.BeginOpen(timeout, callback, state);
  34. }
  35.  
  36. protected override void OnClose(TimeSpan timeout)
  37. {
  38. this.Print("OnClose()");
  39. this.InnerChannel.Close(timeout);
  40. }
  41.  
  42. protected override void OnEndClose(IAsyncResult result)
  43. {
  44. this.Print("OnEndClose()");
  45. this.InnerChannel.EndClose(result);
  46. }
  47.  
  48. protected override void OnEndOpen(IAsyncResult result)
  49. {
  50. this.Print("OnEndOpen()");
  51. this.InnerChannel.EndOpen(result);
  52. }
  53.  
  54. protected override void OnOpen(TimeSpan timeout)
  55. {
  56. this.Print("OnOpen()");
  57. this.InnerChannel.Open(timeout);
  58. }
  59.  
  60. public override T GetProperty<T>()
  61. {
  62. return this.InnerChannel.GetProperty<T>();
  63. }
  64. }
  65. }

自定义请求-回复模式的请求信道

通过继承SimpleChannelBase创建自定义的、在客户端用于发送请求和接收服务端回复的请求信道SimpleRequestChannel 该类不但要继承SimpleChannelBase还需要实现IRequestChannel以模仿请求信道的功能

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public class SimpleRequestChannel : SimpleChannelBase, IRequestChannel
  7. {
  8. public IRequestChannel InnerRequestChannel
  9. {
  10. get { return (IRequestChannel)this.InnerChannel; }
  11. }
  12.  
  13. public SimpleRequestChannel(ChannelManagerBase channelManager, IRequestChannel innerChannel)
  14. : base(channelManager, (ChannelBase)innerChannel)
  15. {
  16. this.Print("SimpleRequestChannel()");
  17. }
  18.  
  19. public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  20. {
  21. this.Print("BeginRequest()");
  22. return this.InnerRequestChannel.BeginRequest(message, timeout, callback, state);
  23. }
  24.  
  25. public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
  26. {
  27. this.Print("BeginRequest()");
  28. return this.InnerRequestChannel.BeginRequest(message, callback, state);
  29. }
  30.  
  31. public Message EndRequest(IAsyncResult result)
  32. {
  33. this.Print("EndRequest()");
  34. return this.InnerRequestChannel.EndRequest(result);
  35. }
  36.  
  37. public EndpointAddress RemoteAddress
  38. {
  39. get { return this.InnerRequestChannel.RemoteAddress; }
  40. }
  41.  
  42. public Message Request(Message message, TimeSpan timeout)
  43. {
  44. this.Print("Request");
  45. return this.InnerRequestChannel.Request(message, timeout);
  46. }
  47.  
  48. public Message Request(Message message)
  49. {
  50. this.Print("Request");
  51. return this.InnerRequestChannel.Request(message);
  52. }
  53.  
  54. public Uri Via
  55. {
  56. get { return this.InnerRequestChannel.Via; }
  57. }
  58. }
  59. }

自定义请求-回复模式的回复信道

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public class SimpleReplyChannel : SimpleChannelBase, IReplyChannel
  7. {
  8. public IReplyChannel InnerReplyChannel
  9. {
  10. get { return (IReplyChannel)this.InnerChannel; }
  11. }
  12.  
  13. public SimpleReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel)
  14. : base(channelManager, (ChannelBase)innerChannel)
  15. {
  16. this.Print("SimpleReplyChannel()");
  17. }
  18.  
  19. public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
  20. {
  21. this.Print("BeginReceiveRequest()");
  22. return this.InnerReplyChannel.BeginReceiveRequest(timeout, callback, state);
  23. }
  24.  
  25. public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
  26. {
  27. this.Print("BeginReceiveRequest()");
  28. return this.InnerReplyChannel.BeginReceiveRequest(callback, state);
  29. }
  30.  
  31. public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
  32. {
  33. this.Print("BeginTryReceiveRequest()");
  34. return this.InnerReplyChannel.BeginTryReceiveRequest(timeout, callback, state);
  35. }
  36.  
  37. public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
  38. {
  39. this.Print("BeginWaitForRequest()");
  40. return this.InnerReplyChannel.BeginWaitForRequest(timeout, callback, state);
  41. }
  42.  
  43. public RequestContext EndReceiveRequest(IAsyncResult result)
  44. {
  45. this.Print("EndReceiveRequest()");
  46. return this.InnerReplyChannel.EndReceiveRequest(result);
  47. }
  48.  
  49. public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
  50. {
  51. this.Print("EndTryReceiveRequest()");
  52. return this.InnerReplyChannel.EndTryReceiveRequest(result, out context);
  53. }
  54.  
  55. public bool EndWaitForRequest(IAsyncResult result)
  56. {
  57. this.Print("EndWaitForRequest()");
  58. return this.InnerReplyChannel.EndWaitForRequest(result);
  59. }
  60.  
  61. public EndpointAddress LocalAddress
  62. {
  63. get{ return this.InnerReplyChannel.LocalAddress;}
  64. }
  65.  
  66. public RequestContext ReceiveRequest(TimeSpan timeout)
  67. {
  68. this.Print("ReceiveRequest()");
  69. return this.InnerReplyChannel.ReceiveRequest(timeout);
  70. }
  71.  
  72. public RequestContext ReceiveRequest()
  73. {
  74. this.Print("ReceiveRequest()");
  75. return this.InnerReplyChannel.ReceiveRequest();
  76. }
  77.  
  78. public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
  79. {
  80. this.Print("TryReceiveRequest()");
  81. return this.InnerReplyChannel.TryReceiveRequest(timeout, out context);
  82. }
  83.  
  84. public bool WaitForRequest(TimeSpan timeout)
  85. {
  86. this.Print("WaitForRequest()");
  87. return this.InnerReplyChannel.WaitForRequest(timeout);
  88. }
  89. }
  90. }

自定义双工会话信道

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public class SimpleDuplexSessionChannel : SimpleChannelBase, IDuplexSessionChannel
  7. {
  8. public IDuplexSessionChannel InnerDuplexSessionChannel
  9. {
  10. get { return (IDuplexSessionChannel)this.InnerChannel; }
  11. }
  12.  
  13. public SimpleDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel)
  14. : base(channelManager, (ChannelBase)innerChannel)
  15. {
  16. this.Print("SimpleDuplexSessionChannel()");
  17. }
  18.  
  19. public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
  20. {
  21. this.Print("BeginReceive()");
  22. return this.InnerDuplexSessionChannel.BeginReceive(timeout, callback, state);
  23. }
  24.  
  25. public IAsyncResult BeginReceive(AsyncCallback callback, object state)
  26. {
  27. this.Print("BeginReceive()");
  28. return this.InnerDuplexSessionChannel.BeginReceive(callback, state);
  29. }
  30.  
  31. public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
  32. {
  33. this.Print("BeginTryReceive()");
  34. return this.InnerDuplexSessionChannel.BeginTryReceive(timeout, callback, state);
  35. }
  36.  
  37. public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
  38. {
  39. this.Print("BeginWaitForMessage()");
  40. return this.InnerDuplexSessionChannel.BeginWaitForMessage(timeout, callback, state);
  41. }
  42.  
  43. public Message EndReceive(IAsyncResult result)
  44. {
  45. this.Print("EndReceive()");
  46. return this.InnerDuplexSessionChannel.EndReceive(result);
  47. }
  48.  
  49. public bool EndTryReceive(IAsyncResult result, out Message message)
  50. {
  51. this.Print("EndTryReceive()");
  52. return this.InnerDuplexSessionChannel.EndTryReceive(result, out message);
  53. }
  54.  
  55. public bool EndWaitForMessage(IAsyncResult result)
  56. {
  57. this.Print("EndWaitForMessage()");
  58. return this.InnerDuplexSessionChannel.EndWaitForMessage(result);
  59. }
  60.  
  61. public EndpointAddress LocalAddress
  62. {
  63. get { return this.InnerDuplexSessionChannel.LocalAddress; }
  64. }
  65.  
  66. public Message Receive(TimeSpan timeout)
  67. {
  68. this.Print("Receive()");
  69. return this.InnerDuplexSessionChannel.Receive(timeout);
  70. }
  71.  
  72. public Message Receive()
  73. {
  74. this.Print("Receive()");
  75. return this.InnerDuplexSessionChannel.Receive();
  76. }
  77.  
  78. public bool TryReceive(TimeSpan timeout, out Message message)
  79. {
  80. this.Print("TryReceive()");
  81. return this.InnerDuplexSessionChannel.TryReceive(timeout, out message);
  82. }
  83.  
  84. public bool WaitForMessage(TimeSpan timeout)
  85. {
  86. this.Print("WaitForMessage()");
  87. return this.InnerDuplexSessionChannel.WaitForMessage(timeout);
  88. }
  89.  
  90. public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  91. {
  92. this.Print("BeginSend()");
  93. return this.InnerDuplexSessionChannel.BeginSend(message, timeout, callback, state);
  94. }
  95.  
  96. public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
  97. {
  98. this.Print("BeginSend()");
  99. return this.InnerDuplexSessionChannel.BeginSend(message, callback, state);
  100. }
  101.  
  102. public void EndSend(IAsyncResult result)
  103. {
  104. this.Print("EndSend()");
  105. this.InnerDuplexSessionChannel.EndSend(result);
  106. }
  107.  
  108. public EndpointAddress RemoteAddress
  109. {
  110. get { return this.InnerDuplexSessionChannel.RemoteAddress; }
  111. }
  112.  
  113. public void Send(Message message, TimeSpan timeout)
  114. {
  115. this.Print("Send()");
  116. this.InnerDuplexSessionChannel.Send(message, timeout);
  117. }
  118.  
  119. public void Send(Message message)
  120. {
  121. this.Print("Send()");
  122. this.InnerDuplexSessionChannel.Send(message);
  123. }
  124.  
  125. public Uri Via
  126. {
  127. get { return this.InnerDuplexSessionChannel.Via; }
  128. }
  129.  
  130. public IDuplexSession Session
  131. {
  132. get { return this.InnerDuplexSessionChannel.Session; }
  133. }
  134. }
  135. }

自定义信道侦听器基类

我们要创建自定义的信道侦听器 则需要继承ChannelListenerBase<TChannel>抽象基类 因为该基类实现了IChannelListener<TChannel>接口 即所有关于侦听器的方法和属性的内部实现都ChannelListenerBase<TChannel>中完成了 我们要定义一个新版的侦听器基类 以便添加新的操作方法 则唯一途径就是派生于ChannelListenerBase<TChannel>类

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public abstract class SimpleChannelListenerBase<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
  6. {
  7. protected void Print(string methodName)
  8. {
  9. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  10. }
  11. public IChannelListener<TChannel> InnerChannelListener { get; private set; }
  12. public SimpleChannelListenerBase(BindingContext context)
  13. {
  14. this.InnerChannelListener = context.BuildInnerChannelListener<TChannel>();
  15. }
  16. protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
  17. {
  18. this.Print("OnBeginAcceptChannel()");
  19. return this.InnerChannelListener.BeginAcceptChannel(timeout, callback, state);
  20. }
  21. protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
  22. {
  23. this.Print("OnBeginWaitForChannel()");
  24. return this.InnerChannelListener.BeginWaitForChannel(timeout, callback, state);
  25. }
  26. protected override bool OnEndWaitForChannel(IAsyncResult result)
  27. {
  28. this.Print("OnEndWaitForChannel()");
  29. return this.InnerChannelListener.EndWaitForChannel(result);
  30. }
  31. protected override bool OnWaitForChannel(TimeSpan timeout)
  32. {
  33. this.Print("OnWaitForChannel()");
  34. return this.InnerChannelListener.WaitForChannel(timeout);
  35. }
  36. public override Uri Uri
  37. {
  38. get{return this.InnerChannelListener.Uri;}
  39. }
  40. protected override void OnAbort()
  41. {
  42. this.Print("OnAbort()");
  43. this.InnerChannelListener.Abort();
  44. }
  45. protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  46. {
  47. this.Print("OnBeginClose()");
  48. return this.InnerChannelListener.BeginClose(timeout, callback, state);
  49. }
  50. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  51. {
  52. this.Print("OnBeginOpen()");
  53. return this.InnerChannelListener.BeginOpen(timeout, callback, state);
  54. }
  55. protected override void OnClose(TimeSpan timeout)
  56. {
  57. this.Print("OnClose()");
  58. this.InnerChannelListener.Close(timeout);
  59. }
  60. protected override void OnEndClose(IAsyncResult result)
  61. {
  62. this.Print("OnEndClose()");
  63. this.InnerChannelListener.EndClose(result);
  64. }
  65. protected override void OnEndOpen(IAsyncResult result)
  66. {
  67. this.Print("OnEndOpen()");
  68. this.InnerChannelListener.EndOpen(result);
  69. }
  70. protected override void OnOpen(TimeSpan timeout)
  71. {
  72. this.Print("OnOpen()");
  73. this.InnerChannelListener.Open(timeout);
  74. }
  75. public override T GetProperty<T>()
  76. {
  77. return this.InnerChannelListener.GetProperty<T>();
  78. }
  79. }
  80. }

自定义基于普通信道的信道侦听器

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleDatagramChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class,IChannel
  6. {
  7. public SimpleDatagramChannelListener(BindingContext context)
  8. : base(context)
  9. {
  10. this.Print("SimpleDatagramChannelListener()");
  11. }
  12. protected override TChannel OnAcceptChannel(TimeSpan timeout)
  13. {
  14. this.Print("OnAcceptChannel()");
  15. IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.AcceptChannel(timeout);
  16. if (null != innerChannel)
  17. {
  18. return new SimpleReplyChannel(this, innerChannel) as TChannel;
  19. }
  20. return null;
  21. }
  22. protected override TChannel OnEndAcceptChannel(IAsyncResult result)
  23. {
  24. this.Print("OnEndAcceptChannel()");
  25. IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.EndAcceptChannel(result);
  26. if (null != innerChannel)
  27. {
  28. return new SimpleReplyChannel(this, innerChannel) as TChannel;
  29. }
  30. return null;
  31. }
  32. }
  33. }

自定义基于会话信道的信道侦听器

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleSessionChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class, IChannel
  6. {
  7. public SimpleSessionChannelListener(BindingContext context)
  8. : base(context)
  9. {
  10. this.Print("SimpleSessionChannelListener()");
  11. }
  12. protected override TChannel OnAcceptChannel(TimeSpan timeout)
  13. {
  14. this.Print("OnAcceptChannel()");
  15. IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.AcceptChannel(timeout);
  16. return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel;
  17. }
  18. protected override TChannel OnEndAcceptChannel(IAsyncResult result)
  19. {
  20. this.Print("OnEndAcceptChannel()");
  21. IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.EndAcceptChannel(result);
  22. if (null != innerChannel)
  23. {
  24. return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel;
  25. }
  26. return default(TChannel);
  27. }
  28. }
  29. }

自定义信道工厂基类

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public abstract class SimpleChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel>
  7. {
  8. protected void Print(string methodName)
  9. {
  10. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  11. }
  12. public IChannelFactory<TChannel> InnerChannelFactory { get; private set; }
  13. public SimpleChannelFactoryBase(BindingContext context)
  14. {
  15. this.InnerChannelFactory = context.BuildInnerChannelFactory<TChannel>();
  16. }
  17. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  18. {
  19. this.Print("OnBeginOpen()");
  20. return this.InnerChannelFactory.BeginOpen(timeout, callback, state);
  21. }
  22.  
  23. protected override void OnEndOpen(IAsyncResult result)
  24. {
  25. this.Print("OnEndOpen()");
  26. this.InnerChannelFactory.EndOpen(result);
  27. }
  28.  
  29. protected override void OnOpen(TimeSpan timeout)
  30. {
  31. this.Print("OnOpen()");
  32. this.InnerChannelFactory.Open(timeout);
  33. }
  34.  
  35. public override T GetProperty<T>()
  36. {
  37. return this.InnerChannelFactory.GetProperty<T>();
  38. }
  39. }
  40. }

自定义基于普通信道的信道工厂

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public class SimpleDatagramChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel>
  7. {
  8. public SimpleDatagramChannelFactory(BindingContext context) :
  9. base(context)
  10. {
  11. this.Print("SimpleDatagramChannelFactory()");
  12. }
  13.  
  14. protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
  15. {
  16. this.Print("OnCreateChannel()");
  17. IRequestChannel innerChannel = (IRequestChannel)this.InnerChannelFactory.CreateChannel(address, via);
  18. if (null != innerChannel)
  19. {
  20. return (TChannel)(object)new SimpleRequestChannel(this, innerChannel);
  21. }
  22. else
  23. {
  24. return default(TChannel);
  25. }
  26. }
  27. }
  28. }

自定义基于会话信道的信道工厂

  1. using System.ServiceModel.Channels;
  2. using System.ServiceModel;
  3.  
  4. namespace Custom
  5. {
  6. public class SimpleSessionChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel>
  7. {
  8. public SimpleSessionChannelFactory(BindingContext context)
  9. : base(context)
  10. {
  11. this.Print("SimpleSessionChannelFactory()");
  12. }
  13. protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
  14. {
  15. this.Print("OnCreateChannel()");
  16. IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelFactory.CreateChannel(address, via);
  17. if (null != innerChannel)
  18. {
  19. return (TChannel)(object)new SimpleDuplexSessionChannel(this, innerChannel);
  20. }
  21. return default(TChannel);
  22. }
  23. }
  24. }

自定义基于普通信道的绑定元素

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleDatagramBindingElement:BindingElement
  6. {
  7. protected void Print(string methodName)
  8. {
  9. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  10. }
  11. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
  12. {
  13. this.Print("BuildChannelListener<TChannel>()");
  14. return new SimpleDatagramChannelListener<TChannel>(context);
  15. }
  16. public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
  17. {
  18. this.Print("BuildChannelFactory<TChannel>()");
  19. return new SimpleDatagramChannelFactory<TChannel>(context);
  20. }
  21.  
  22. public override BindingElement Clone()
  23. {
  24. return new SimpleDatagramBindingElement();
  25. }
  26. public override T GetProperty<T>(BindingContext context)
  27. {
  28. return context.GetInnerProperty<T>();
  29. }
  30. }
  31. }

自定义基于会话信道的绑定元素

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleSessionBindingElement: BindingElement
  6. {
  7. protected void Print(string methodName)
  8. {
  9. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  10. }
  11. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
  12. {
  13. this.Print("BuildChannelListener<TChannel>()");
  14. return new SimpleSessionChannelListener<TChannel>(context);
  15. }
  16. public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
  17. {
  18. this.Print("BuildChannelFactory<TChannel>()");
  19. return new SimpleSessionChannelFactory<TChannel>(context);
  20. }
  21. public override BindingElement Clone()
  22. {
  23. return new SimpleSessionBindingElement();
  24. }
  25. public override T GetProperty<T>(BindingContext context)
  26. {
  27. return context.GetInnerProperty<T>();
  28. }
  29. }
  30. }

自定义基于普通信道的绑定对象

在前面的示例中 我们创建了自定义的信道、信道侦听器和信道工厂、绑定元素 所有这些对象都必须通过一个具体的绑定对象才能将它们全部应用到WCF运行环境中

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleDatagramBinding : Binding
  6. {
  7. protected void Print(string methodName)
  8. {
  9. Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
  10. }
  11. private TransportBindingElement transportBindingElement;
  12. private BindingElementCollection bindingElementCollection;
  13. public SimpleDatagramBinding()
  14. {
  15. BindingElement[] bindingElements = new BindingElement[]
  16. {
  17. new SimpleDatagramBindingElement(),
  18. new TextMessageEncodingBindingElement(),
  19. new HttpTransportBindingElement()
  20. };
  21. bindingElementCollection = new BindingElementCollection(bindingElements);
  22. transportBindingElement = (TransportBindingElement)bindingElements[];
  23. }
  24. public override BindingElementCollection CreateBindingElements()
  25. {
  26. return bindingElementCollection;
  27. }
  28. public override string Scheme
  29. {
  30. get { return transportBindingElement.Scheme; }
  31. }
  32. }
  33. }

自定义基于会话信道的绑定对象

  1. using System.ServiceModel.Channels;
  2.  
  3. namespace Custom
  4. {
  5. public class SimpleSessionBinding : Binding
  6. {
  7. private TransportBindingElement transportBindingElement;
  8. private BindingElementCollection bindingElementCollection;
  9. public SimpleSessionBinding()
  10. {
  11. BindingElement[] bindingElements = new BindingElement[]
  12. {
  13. new SimpleSessionBindingElement(),
  14. new BinaryMessageEncodingBindingElement(),
  15. new TcpTransportBindingElement()
  16. };
  17. bindingElementCollection = new BindingElementCollection(bindingElements);
  18. transportBindingElement = (TransportBindingElement)bindingElements[];
  19. }
  20. public override BindingElementCollection CreateBindingElements()
  21. {
  22. return bindingElementCollection;
  23. }
  24. public override string Scheme
  25. {
  26. get { return transportBindingElement.Scheme; }
  27. }
  28. }
  29. }

测试自定义绑定对象

我们使用这个自定义绑定对象来做测试 修改计算服务的例子 打开Service项目的CalculatorService文件 修改如下

  1. using Service.Interface;
  2.  
  3. namespace Service
  4. {
  5. public class CalculatorService:ICalculator
  6. {
  7. public double Add(double x, double y)
  8. {
  9. var result = x + y;
  10. Console.WriteLine("完成接收请求和回复…………");
  11. return result;
  12. }
  13. }
  14. }

打开Hosting项目的入口文件 修改如下

  1. using System.ServiceModel;
  2. using Service.Interface;
  3. using Service;
  4. using Custom;
  5.  
  6. namespace Hosting
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. ServiceHost host = new ServiceHost(typeof(CalculatorService));
  13. host.AddServiceEndpoint(typeof(ICalculator), new SimpleDatagramBinding(), "http://127.0.0.1:7777/calculatorservice");
  14. host.Open();
  15. Console.WriteLine("服务已开启……");
  16. Console.Read();
  17. }
  18. }
  19. }

用管理员身份运行该程序 则会输出以下信息

SimpleDatagramBindingElement.BuildChannelListener<TChannel>() 
SimpleDatagramChannelListener`1.SimpleDatagramChannelListener()
SimpleDatagramChannelListener`1.OnOpen() 
服务已开启……
SimpleDatagramChannelListener`1.OnBeginAcceptChannel() 
SimpleDatagramChannelListener`1.OnEndAcceptChannel() 
SimpleReplyChannel.SimpleReplyChannel() 
SimpleDatagramChannelListener`1.OnBeginAcceptChannel() 
SimpleReplyChannel.OnOpen() 
SimpleReplyChannel.BeginTryReceiveRequest()

绑定对象创建信道侦听器的流程

WsHttpBinding是一个内置的绑定对象 WsHttpBinding被实例化时 它会调用自身的BuildChannelListener<TChannel>()方法创建信道侦听器管道 因为它有

两个内置的绑定元素HttpTransportBindingElement(传输元素)和TextMessageEncodingBindingElement(编码元素)两个绑定元素会自动创建自身的

信道侦听器 前一个侦听器侦听到请求就会传输信息到客户端 后一个侦听器侦听到请求则会处理请求中的信息编码

接着我们来看上面的例子 通过实例化自定义的绑定元素后 程序如何执行的 首先new SimpleDatagramBinding()执行时 将创建自定义绑定对象 - 绑定对象自动调用自身的BuildChannelListener<TChannel>()方法创建信道侦听器管道 我们可以把这个管道理解为一个大的侦听器容器(信道栈) 它承载的是绑定对象中的每个绑定元素自动创建的对应的侦听器 多个侦听器存储在这个信道侦听器通道中 该通道被打开以便侦听请求的信息 请求信息一旦抵达 通道则将依次调用每个绑定元素对应的信道的方法

  1. SimpleDatagramBindingElement.BuildChannelListener<TChannel>() //自定义绑定元素调用该方法创建了一个自定义的信道侦听器
  2. SimpleDatagramChannelListener`.SimpleDatagramChannelListener() //自定义的信道侦听器被实例化
  3. SimpleDatagramChannelListener`.OnOpen() //自定义的信道侦听器创建完成后自动打开以便侦听请求
  4. 服务已开启……
  5. SimpleDatagramChannelListener`.OnBeginAcceptChannel() //信道侦听器在开始创建信道时将触发这个事件
  6. SimpleDatagramChannelListener`.OnEndAcceptChannel() //信道侦听器在创建完信道时将触发这个事件
  7. SimpleReplyChannel.SimpleReplyChannel() //信道侦听器创建了一个回复信道
  8. SimpleDatagramChannelListener`.OnBeginAcceptChannel() //信道被创建 则该事件被触发
  9. SimpleReplyChannel.OnOpen() //打开回复信道 以便回复信息
  10. SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作

在我们自定义的绑定对象中 除了自定义的绑定元素 还有两个绑定元素被添加到绑定对象中 如下代码片段所示:

  1. public SimpleDatagramBinding()
  2. {
  3.   BindingElement[] bindingElements = new BindingElement[]
  4.   {
  5.     new SimpleDatagramBindingElement(), //自定义的绑定元素
  6.     new TextMessageEncodingBindingElement(), //编码绑定元素
  7.     new HttpTransportBindingElement() //传输绑定元素
  8.   };
  9.   bindingElementCollection = new BindingElementCollection(bindingElements);
  10.   transportBindingElement = (TransportBindingElement)bindingElements[];
  11. }

一个是用于传输的绑定元素HttpTransportBindingElemen和用于编码的绑定元素SimpleDatagramBindingElement 两个绑定元素也都会调用自身的BuildChannelListener<TChannel>()方法创建各自的信道侦听器(隐式的创建了信道侦听器同时传输绑定元素还隐式创建了传输信道 而编码绑定元素隐式创建了编码信道) 这些信道再加上上面的自定义绑定元素创建的信道侦听器 就组成了一个信道栈(即信道通道)

接着我们打开Client项目的入口文件 修改如下:

  1. using System.ServiceModel;
  2. using Service.Interface;
  3. using Custom;
  4.  
  5. namespace Client
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. EndpointAddress pointAddress=new EndpointAddress("http://127.0.0.1:7777/calculatorservice");
  12. ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new SimpleDatagramBinding(), pointAddress);
  13. //第一个信道工厂创建的服务代理
  14. ICalculator proxy = channelFactory.CreateChannel();
  15. //发送第一个请求
  16. proxy.Add(, );
  17. Console.WriteLine("完成请求并接收到回复……");
  18. //发送第二个请求
  19. proxy.Add(, );
  20. Console.WriteLine("完成请求并接收到回复……");
  21. (proxy as ICommunicationObject).Close();
  22.  
  23. //第二个信道工厂创建的服务代理
  24. proxy = channelFactory.CreateChannel();
  25. //发送第一个请求
  26. proxy.Add(, );
  27. Console.WriteLine("完成请求并接收到回复……");
  28. //发送第二个请求
  29. proxy.Add(, );
  30. Console.WriteLine("完成请求并接收到回复……");
  31. (proxy as ICommunicationObject).Close();
  32. }
  33. }
  34. }

保持Hosting的运行 在运行Client 输出如下

new SimpleDatagramBinding()被实例化 - 它调用自身的BuildChannelFactory<TChannel>()方法创建信道工厂管道 因为它有两个内置的绑定元素TextMessageEncodingBindingElement(编码元素)和HttpTransportBindingElement(传输元素)两个绑定元素会自动创建自身的信道工厂 前一个信道工厂通过编码信道将信息编码接着使用后一个信道工厂通过传输信道发送信息请求到服务端

  1. SimpleDatagramBindingElement.BuildChannelFactory<TChannel>() //自定义的绑定元素调用该方法创建了一个信道工厂
  2. SimpleDatagramChannelFactory`.SimpleDatagramChannelFactory() //自定义的信道工厂被初始化
  3. SimpleDatagramChannelFactory`.OnOpen() //自定义的信道工厂在开启时将触发这个事件
  4. SimpleDatagramChannelFactory`.OnCreateChannel() //自定义的信道工厂在开始创建请求信道时将触发这个事件
  5. SimpleRequestChannel.SimpleRequestChannel() //自定义的信道工厂创建了一个自定义的请求信道
  6. SimpleRequestChannel.OnOpen() //自定义的请求信道自动开启
  7. SimpleRequestChannel.Request //自定义的请求信道发送发送第一个请求并接收服务端的回复信息
  8. 完成请求并接收到回复……
  9. SimpleRequestChannel.Request //自定义的请求信道发送发送第二个请求并接收服务端的回复信息
  10. 完成请求并接收到回复……
  11. SimpleRequestChannel.OnClose() //第一个服务代理被关闭 此时信道工厂管道并没关闭 它所有的信道还存在 请参看代码 关闭的是代理对象
  12. SimpleDatagramChannelFactory`.OnCreateChannel() //自定义的信道工厂在开始创建请求信道时将触发这个事件
  13. SimpleRequestChannel.SimpleRequestChannel() //重复以上步骤
  14. SimpleRequestChannel.OnOpen() //重复以上步骤
  15. SimpleRequestChannel.Request //重复以上步骤
  16. 完成请求并接收到回复……
  17. SimpleRequestChannel.Request
  18. 完成请求并接收到回复……
  19. SimpleRequestChannel.OnClose() //重复以上步骤

而此时在服务端因为侦听到了请求 所以会如下输出信息

  1. SimpleDatagramBindingElement.BuildChannelListener<TChannel>() //自定义绑定元素调用该方法创建了一个自定义的信道侦听器
  2. SimpleDatagramChannelListener`.SimpleDatagramChannelListener() //自定义的信道侦听器被实例化
  3. SimpleDatagramChannelListener`.OnOpen() //自定义的信道侦听器创建完成后自动打开以便侦听请求
  4. 服务已开启……
  5. SimpleDatagramChannelListener`.OnBeginAcceptChannel() SimpleDatagramChannelListener`.OnEndAcceptChannel()
  6. SimpleReplyChannel.SimpleReplyChannel() //信道侦听器创建了一个回复信道
  7. SimpleDatagramChannelListener`.OnBeginAcceptChannel()
  8. SimpleReplyChannel.OnOpen() //打开回复信道 以便回复信息
  9. SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作
  10. SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作
  11. SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第一个请求抵达
  12. 完成接收请求和回复……
  13. SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作
  14. SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第二个请求抵达
  15. 完成接收请求和回复……
  16. SimpleReplyChannel.EndTryReceiveRequest() //重复
  17. SimpleReplyChannel.BeginTryReceiveRequest() //重复
  18. 完成接收请求和回复……
  19. SimpleReplyChannel.EndTryReceiveRequest() //重复
  20. SimpleReplyChannel.BeginTryReceiveRequest() //重复
  21. 完成接收请求和回复……

WCF - 学习总目录

WCF - 绑定后续之自定义绑定的更多相关文章

  1. WCF - 自定义绑定

    自定义绑定 当系统提供的某个绑定不符合服务的要求时,可使用 CustomBinding 类.所有绑定都是从绑定元素的有序集构造而来的.自定义绑定可以从一组系统提供的绑定元素生成,也可以包含用户定义的自 ...

  2. WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(二)实现IRequestChannel(2016-03-15 12:35)

    这是这个系列的第二篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...

  3. WCF 项目应用连载[8] - 绑定、服务、行为 大数据传输与限流 - 下 (ServiceThrottlingAttribute)

    因为ORM的原因,对Attribute编程有一种情节..所以这节的出现,完全是因为在WCF对自定义Attribute的一种应用. WCF 项目应用连载[7] - 绑定.服务.行为 大数据传输与限流 - ...

  4. KNOCKOUTJS DOCUMENTATION-绑定(BINDINGS)-自定义绑定

    除了ko内建的绑定,还可以自定义绑定,灵活地封装复杂的行为使之可重用. 自定义绑定 注册自定义绑定 向 ko.bindingHandles添加一个子属性来注册一个绑定. ko.bindingHandl ...

  5. Maven自定义绑定插件目标:创建项目的源码jar

    <build> <plugins> <!-- 自定义绑定,创建项目的源码jar --> <plugin> <groupId>org.apac ...

  6. 背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换

    [源码下载] 背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换 作者:webabcd 介 ...

  7. KnockoutJS 3.X API 第五章 高级应用(1) 创建自定义绑定

    您不仅限于使用内置的绑定,如click,value绑定等,您可以创建自己的绑定. 这是如何控制视图模型如何与DOM元素进行交互,并且为您提供了大量的灵活性,以便于以复用的方式封装复杂的行为. 注册绑定 ...

  8. 5.Knockout.Js(自定义绑定)

    前言 你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等).你可以你封装复杂的逻辑或行为,自定义很容易使用和重用的绑定.例如,你可以在form表单里自定义像grid ...

  9. 【Knockout】五、创建自定义绑定

    概述 除了上一篇列出的KO内置的绑定类型(如value.text等),你也可以创建自定义绑定. 注册你的binding handler ko.bindingHandlers.yourBindingNa ...

随机推荐

  1. 【python之旅】python简介和入门

    python简介: 一.什么是python python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了打发时间,决心开发一个新的脚本解释程序, ...

  2. MAC 使用Jetbrains's产品

    Jetbrains's MAC 使用 ./gradle fatjar 或者 ./gradlew.sh fatjar java -jar build/lib/xx.jar 链接: http://pan. ...

  3. 学习Swift--下标脚本

    下标脚本 下标脚本可以定义在类(Class).结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问集合(collection),列表(list)或序列(sequenc ...

  4. 游戏服务器:到底使用UDP还是TCP

    http://blog.jobbole.com/64638/ 在编写网络游戏的时候,到底使用UDP还是TCP的问题迟早都要面对. 一般来说你会听到人们这样说:“除非你正在写一个动作类游戏,否则你就用T ...

  5. jsonp跨域问题记录

    这段时间用H5做移动app开发,遇到不少之前做web的时候不曾遇到的问题,记录一下,共勉-- 首先说一个:js跨域取数的问题 描述:  之前做web都是通过后台获取数据,没考虑过跨域的问题.这次用h5 ...

  6. 【HDU3948】 The Number of Palindromes (后缀数组+RMQ)

    The Number of Palindromes Problem Description Now, you are given a string S. We want to know how man ...

  7. android通用文件操作

    最经用到android的SCCard的文件操作,因此稍作了整理,将它写成一个简单的工具类.其中,可以判断SDCard的是否可用,可用存储空间,文件的创建以及写入数据.经过测试,可以正常使用.代码如下: ...

  8. Scala:(2)控制结构

    (1)if else val s=) else -1 (2)循环 ){ r=r*n n-= } ///for 循环 to n) r=r*i //until val s="Hello" ...

  9. VisualBox ubuntu14.04 64位 android4.4.4源码编译总结

    转载请保留出处:http://www.cnblogs.com/wi100sh/p/4337907.html 折腾了好几天,今天终于编译通过,用了4个多小时,太不容易了.如下图所示: 软件环境 虚拟机: ...

  10. C++ string 构造的陷阱

    先看代码 #include<iostream> #include<string> using namespace std; int main(int argc, char ** ...