自定义信道基类

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

 using System.ServiceModel.Channels;

 namespace Custom
{
public abstract class SimpleChannelBase : ChannelBase
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
public ChannelBase InnerChannel { get; private set; }
public SimpleChannelBase(ChannelManagerBase channelManager, ChannelBase innerChannel)
: base(channelManager)
{
this.InnerChannel = innerChannel;
} protected override void OnAbort()
{
this.Print("OnAbort()");
this.InnerChannel.Abort();
} protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginClose()");
return this.InnerChannel.BeginClose(timeout, callback, state);
} protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginOpen()");
return this.InnerChannel.BeginOpen(timeout, callback, state);
} protected override void OnClose(TimeSpan timeout)
{
this.Print("OnClose()");
this.InnerChannel.Close(timeout);
} protected override void OnEndClose(IAsyncResult result)
{
this.Print("OnEndClose()");
this.InnerChannel.EndClose(result);
} protected override void OnEndOpen(IAsyncResult result)
{
this.Print("OnEndOpen()");
this.InnerChannel.EndOpen(result);
} protected override void OnOpen(TimeSpan timeout)
{
this.Print("OnOpen()");
this.InnerChannel.Open(timeout);
} public override T GetProperty<T>()
{
return this.InnerChannel.GetProperty<T>();
}
}
}

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

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

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public class SimpleRequestChannel : SimpleChannelBase, IRequestChannel
{
public IRequestChannel InnerRequestChannel
{
get { return (IRequestChannel)this.InnerChannel; }
} public SimpleRequestChannel(ChannelManagerBase channelManager, IRequestChannel innerChannel)
: base(channelManager, (ChannelBase)innerChannel)
{
this.Print("SimpleRequestChannel()");
} public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginRequest()");
return this.InnerRequestChannel.BeginRequest(message, timeout, callback, state);
} public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
{
this.Print("BeginRequest()");
return this.InnerRequestChannel.BeginRequest(message, callback, state);
} public Message EndRequest(IAsyncResult result)
{
this.Print("EndRequest()");
return this.InnerRequestChannel.EndRequest(result);
} public EndpointAddress RemoteAddress
{
get { return this.InnerRequestChannel.RemoteAddress; }
} public Message Request(Message message, TimeSpan timeout)
{
this.Print("Request");
return this.InnerRequestChannel.Request(message, timeout);
} public Message Request(Message message)
{
this.Print("Request");
return this.InnerRequestChannel.Request(message);
} public Uri Via
{
get { return this.InnerRequestChannel.Via; }
}
}
}

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

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public class SimpleReplyChannel : SimpleChannelBase, IReplyChannel
{
public IReplyChannel InnerReplyChannel
{
get { return (IReplyChannel)this.InnerChannel; }
} public SimpleReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel)
: base(channelManager, (ChannelBase)innerChannel)
{
this.Print("SimpleReplyChannel()");
} public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginReceiveRequest()");
return this.InnerReplyChannel.BeginReceiveRequest(timeout, callback, state);
} public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
{
this.Print("BeginReceiveRequest()");
return this.InnerReplyChannel.BeginReceiveRequest(callback, state);
} public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginTryReceiveRequest()");
return this.InnerReplyChannel.BeginTryReceiveRequest(timeout, callback, state);
} public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginWaitForRequest()");
return this.InnerReplyChannel.BeginWaitForRequest(timeout, callback, state);
} public RequestContext EndReceiveRequest(IAsyncResult result)
{
this.Print("EndReceiveRequest()");
return this.InnerReplyChannel.EndReceiveRequest(result);
} public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
{
this.Print("EndTryReceiveRequest()");
return this.InnerReplyChannel.EndTryReceiveRequest(result, out context);
} public bool EndWaitForRequest(IAsyncResult result)
{
this.Print("EndWaitForRequest()");
return this.InnerReplyChannel.EndWaitForRequest(result);
} public EndpointAddress LocalAddress
{
get{ return this.InnerReplyChannel.LocalAddress;}
} public RequestContext ReceiveRequest(TimeSpan timeout)
{
this.Print("ReceiveRequest()");
return this.InnerReplyChannel.ReceiveRequest(timeout);
} public RequestContext ReceiveRequest()
{
this.Print("ReceiveRequest()");
return this.InnerReplyChannel.ReceiveRequest();
} public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
{
this.Print("TryReceiveRequest()");
return this.InnerReplyChannel.TryReceiveRequest(timeout, out context);
} public bool WaitForRequest(TimeSpan timeout)
{
this.Print("WaitForRequest()");
return this.InnerReplyChannel.WaitForRequest(timeout);
}
}
}

自定义双工会话信道

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public class SimpleDuplexSessionChannel : SimpleChannelBase, IDuplexSessionChannel
{
public IDuplexSessionChannel InnerDuplexSessionChannel
{
get { return (IDuplexSessionChannel)this.InnerChannel; }
} public SimpleDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel)
: base(channelManager, (ChannelBase)innerChannel)
{
this.Print("SimpleDuplexSessionChannel()");
} public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginReceive()");
return this.InnerDuplexSessionChannel.BeginReceive(timeout, callback, state);
} public IAsyncResult BeginReceive(AsyncCallback callback, object state)
{
this.Print("BeginReceive()");
return this.InnerDuplexSessionChannel.BeginReceive(callback, state);
} public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginTryReceive()");
return this.InnerDuplexSessionChannel.BeginTryReceive(timeout, callback, state);
} public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginWaitForMessage()");
return this.InnerDuplexSessionChannel.BeginWaitForMessage(timeout, callback, state);
} public Message EndReceive(IAsyncResult result)
{
this.Print("EndReceive()");
return this.InnerDuplexSessionChannel.EndReceive(result);
} public bool EndTryReceive(IAsyncResult result, out Message message)
{
this.Print("EndTryReceive()");
return this.InnerDuplexSessionChannel.EndTryReceive(result, out message);
} public bool EndWaitForMessage(IAsyncResult result)
{
this.Print("EndWaitForMessage()");
return this.InnerDuplexSessionChannel.EndWaitForMessage(result);
} public EndpointAddress LocalAddress
{
get { return this.InnerDuplexSessionChannel.LocalAddress; }
} public Message Receive(TimeSpan timeout)
{
this.Print("Receive()");
return this.InnerDuplexSessionChannel.Receive(timeout);
} public Message Receive()
{
this.Print("Receive()");
return this.InnerDuplexSessionChannel.Receive();
} public bool TryReceive(TimeSpan timeout, out Message message)
{
this.Print("TryReceive()");
return this.InnerDuplexSessionChannel.TryReceive(timeout, out message);
} public bool WaitForMessage(TimeSpan timeout)
{
this.Print("WaitForMessage()");
return this.InnerDuplexSessionChannel.WaitForMessage(timeout);
} public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("BeginSend()");
return this.InnerDuplexSessionChannel.BeginSend(message, timeout, callback, state);
} public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
{
this.Print("BeginSend()");
return this.InnerDuplexSessionChannel.BeginSend(message, callback, state);
} public void EndSend(IAsyncResult result)
{
this.Print("EndSend()");
this.InnerDuplexSessionChannel.EndSend(result);
} public EndpointAddress RemoteAddress
{
get { return this.InnerDuplexSessionChannel.RemoteAddress; }
} public void Send(Message message, TimeSpan timeout)
{
this.Print("Send()");
this.InnerDuplexSessionChannel.Send(message, timeout);
} public void Send(Message message)
{
this.Print("Send()");
this.InnerDuplexSessionChannel.Send(message);
} public Uri Via
{
get { return this.InnerDuplexSessionChannel.Via; }
} public IDuplexSession Session
{
get { return this.InnerDuplexSessionChannel.Session; }
}
}
}

自定义信道侦听器基类

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

using System.ServiceModel.Channels;

namespace Custom
{
public abstract class SimpleChannelListenerBase<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
public IChannelListener<TChannel> InnerChannelListener { get; private set; }
public SimpleChannelListenerBase(BindingContext context)
{
this.InnerChannelListener = context.BuildInnerChannelListener<TChannel>();
}
protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginAcceptChannel()");
return this.InnerChannelListener.BeginAcceptChannel(timeout, callback, state);
}
protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginWaitForChannel()");
return this.InnerChannelListener.BeginWaitForChannel(timeout, callback, state);
}
protected override bool OnEndWaitForChannel(IAsyncResult result)
{
this.Print("OnEndWaitForChannel()");
return this.InnerChannelListener.EndWaitForChannel(result);
}
protected override bool OnWaitForChannel(TimeSpan timeout)
{
this.Print("OnWaitForChannel()");
return this.InnerChannelListener.WaitForChannel(timeout);
}
public override Uri Uri
{
get{return this.InnerChannelListener.Uri;}
}
protected override void OnAbort()
{
this.Print("OnAbort()");
this.InnerChannelListener.Abort();
}
protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginClose()");
return this.InnerChannelListener.BeginClose(timeout, callback, state);
}
protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginOpen()");
return this.InnerChannelListener.BeginOpen(timeout, callback, state);
}
protected override void OnClose(TimeSpan timeout)
{
this.Print("OnClose()");
this.InnerChannelListener.Close(timeout);
}
protected override void OnEndClose(IAsyncResult result)
{
this.Print("OnEndClose()");
this.InnerChannelListener.EndClose(result);
}
protected override void OnEndOpen(IAsyncResult result)
{
this.Print("OnEndOpen()");
this.InnerChannelListener.EndOpen(result);
}
protected override void OnOpen(TimeSpan timeout)
{
this.Print("OnOpen()");
this.InnerChannelListener.Open(timeout);
}
public override T GetProperty<T>()
{
return this.InnerChannelListener.GetProperty<T>();
}
}
}

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleDatagramChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class,IChannel
{
public SimpleDatagramChannelListener(BindingContext context)
: base(context)
{
this.Print("SimpleDatagramChannelListener()");
}
protected override TChannel OnAcceptChannel(TimeSpan timeout)
{
this.Print("OnAcceptChannel()");
IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.AcceptChannel(timeout);
if (null != innerChannel)
{
return new SimpleReplyChannel(this, innerChannel) as TChannel;
}
return null;
}
protected override TChannel OnEndAcceptChannel(IAsyncResult result)
{
this.Print("OnEndAcceptChannel()");
IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.EndAcceptChannel(result);
if (null != innerChannel)
{
return new SimpleReplyChannel(this, innerChannel) as TChannel;
}
return null;
}
}
}

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleSessionChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class, IChannel
{
public SimpleSessionChannelListener(BindingContext context)
: base(context)
{
this.Print("SimpleSessionChannelListener()");
}
protected override TChannel OnAcceptChannel(TimeSpan timeout)
{
this.Print("OnAcceptChannel()");
IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.AcceptChannel(timeout);
return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel;
}
protected override TChannel OnEndAcceptChannel(IAsyncResult result)
{
this.Print("OnEndAcceptChannel()");
IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.EndAcceptChannel(result);
if (null != innerChannel)
{
return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel;
}
return default(TChannel);
}
}
}

自定义信道工厂基类

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public abstract class SimpleChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel>
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
public IChannelFactory<TChannel> InnerChannelFactory { get; private set; }
public SimpleChannelFactoryBase(BindingContext context)
{
this.InnerChannelFactory = context.BuildInnerChannelFactory<TChannel>();
}
protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
{
this.Print("OnBeginOpen()");
return this.InnerChannelFactory.BeginOpen(timeout, callback, state);
} protected override void OnEndOpen(IAsyncResult result)
{
this.Print("OnEndOpen()");
this.InnerChannelFactory.EndOpen(result);
} protected override void OnOpen(TimeSpan timeout)
{
this.Print("OnOpen()");
this.InnerChannelFactory.Open(timeout);
} public override T GetProperty<T>()
{
return this.InnerChannelFactory.GetProperty<T>();
}
}
}

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

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public class SimpleDatagramChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel>
{
public SimpleDatagramChannelFactory(BindingContext context) :
base(context)
{
this.Print("SimpleDatagramChannelFactory()");
} protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
{
this.Print("OnCreateChannel()");
IRequestChannel innerChannel = (IRequestChannel)this.InnerChannelFactory.CreateChannel(address, via);
if (null != innerChannel)
{
return (TChannel)(object)new SimpleRequestChannel(this, innerChannel);
}
else
{
return default(TChannel);
}
}
}
}

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

using System.ServiceModel.Channels;
using System.ServiceModel; namespace Custom
{
public class SimpleSessionChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel>
{
public SimpleSessionChannelFactory(BindingContext context)
: base(context)
{
this.Print("SimpleSessionChannelFactory()");
}
protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
{
this.Print("OnCreateChannel()");
IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelFactory.CreateChannel(address, via);
if (null != innerChannel)
{
return (TChannel)(object)new SimpleDuplexSessionChannel(this, innerChannel);
}
return default(TChannel);
}
}
}

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleDatagramBindingElement:BindingElement
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
this.Print("BuildChannelListener<TChannel>()");
return new SimpleDatagramChannelListener<TChannel>(context);
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
this.Print("BuildChannelFactory<TChannel>()");
return new SimpleDatagramChannelFactory<TChannel>(context);
} public override BindingElement Clone()
{
return new SimpleDatagramBindingElement();
}
public override T GetProperty<T>(BindingContext context)
{
return context.GetInnerProperty<T>();
}
}
}

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleSessionBindingElement: BindingElement
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
this.Print("BuildChannelListener<TChannel>()");
return new SimpleSessionChannelListener<TChannel>(context);
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
this.Print("BuildChannelFactory<TChannel>()");
return new SimpleSessionChannelFactory<TChannel>(context);
}
public override BindingElement Clone()
{
return new SimpleSessionBindingElement();
}
public override T GetProperty<T>(BindingContext context)
{
return context.GetInnerProperty<T>();
}
}
}

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

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleDatagramBinding : Binding
{
protected void Print(string methodName)
{
Console.WriteLine("{0}.{1}", this.GetType().Name, methodName);
}
private TransportBindingElement transportBindingElement;
private BindingElementCollection bindingElementCollection;
public SimpleDatagramBinding()
{
BindingElement[] bindingElements = new BindingElement[]
{
new SimpleDatagramBindingElement(),
new TextMessageEncodingBindingElement(),
new HttpTransportBindingElement()
};
bindingElementCollection = new BindingElementCollection(bindingElements);
transportBindingElement = (TransportBindingElement)bindingElements[];
}
public override BindingElementCollection CreateBindingElements()
{
return bindingElementCollection;
}
public override string Scheme
{
get { return transportBindingElement.Scheme; }
}
}
}

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

using System.ServiceModel.Channels;

namespace Custom
{
public class SimpleSessionBinding : Binding
{
private TransportBindingElement transportBindingElement;
private BindingElementCollection bindingElementCollection;
public SimpleSessionBinding()
{
BindingElement[] bindingElements = new BindingElement[]
{
new SimpleSessionBindingElement(),
new BinaryMessageEncodingBindingElement(),
new TcpTransportBindingElement()
};
bindingElementCollection = new BindingElementCollection(bindingElements);
transportBindingElement = (TransportBindingElement)bindingElements[];
}
public override BindingElementCollection CreateBindingElements()
{
return bindingElementCollection;
}
public override string Scheme
{
get { return transportBindingElement.Scheme; }
}
}
}

测试自定义绑定对象

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

 using Service.Interface;

 namespace Service
{
public class CalculatorService:ICalculator
{
public double Add(double x, double y)
{
var result = x + y;
Console.WriteLine("完成接收请求和回复…………");
return result;
}
}
}

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

 using System.ServiceModel;
using Service.Interface;
using Service;
using Custom; namespace Hosting
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(CalculatorService));
host.AddServiceEndpoint(typeof(ICalculator), new SimpleDatagramBinding(), "http://127.0.0.1:7777/calculatorservice");
host.Open();
Console.WriteLine("服务已开启……");
Console.Read();
}
}
}

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

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>()方法创建信道侦听器管道 我们可以把这个管道理解为一个大的侦听器容器(信道栈) 它承载的是绑定对象中的每个绑定元素自动创建的对应的侦听器 多个侦听器存储在这个信道侦听器通道中 该通道被打开以便侦听请求的信息 请求信息一旦抵达 通道则将依次调用每个绑定元素对应的信道的方法

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

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

 public SimpleDatagramBinding()
{
  BindingElement[] bindingElements = new BindingElement[]
  {
    new SimpleDatagramBindingElement(), //自定义的绑定元素
    new TextMessageEncodingBindingElement(), //编码绑定元素
    new HttpTransportBindingElement() //传输绑定元素
  };
  bindingElementCollection = new BindingElementCollection(bindingElements);
  transportBindingElement = (TransportBindingElement)bindingElements[];
}

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

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

 using System.ServiceModel;
using Service.Interface;
using Custom; namespace Client
{
class Program
{
static void Main(string[] args)
{
EndpointAddress pointAddress=new EndpointAddress("http://127.0.0.1:7777/calculatorservice");
ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new SimpleDatagramBinding(), pointAddress);
//第一个信道工厂创建的服务代理
ICalculator proxy = channelFactory.CreateChannel();
//发送第一个请求
proxy.Add(, );
Console.WriteLine("完成请求并接收到回复……");
//发送第二个请求
proxy.Add(, );
Console.WriteLine("完成请求并接收到回复……");
(proxy as ICommunicationObject).Close(); //第二个信道工厂创建的服务代理
proxy = channelFactory.CreateChannel();
//发送第一个请求
proxy.Add(, );
Console.WriteLine("完成请求并接收到回复……");
//发送第二个请求
proxy.Add(, );
Console.WriteLine("完成请求并接收到回复……");
(proxy as ICommunicationObject).Close();
}
}
}

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

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

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

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

 SimpleDatagramBindingElement.BuildChannelListener<TChannel>() //自定义绑定元素调用该方法创建了一个自定义的信道侦听器
SimpleDatagramChannelListener`.SimpleDatagramChannelListener() //自定义的信道侦听器被实例化
SimpleDatagramChannelListener`.OnOpen() //自定义的信道侦听器创建完成后自动打开以便侦听请求
服务已开启……
SimpleDatagramChannelListener`.OnBeginAcceptChannel() SimpleDatagramChannelListener`.OnEndAcceptChannel()
SimpleReplyChannel.SimpleReplyChannel() //信道侦听器创建了一个回复信道
SimpleDatagramChannelListener`.OnBeginAcceptChannel()
SimpleReplyChannel.OnOpen() //打开回复信道 以便回复信息
SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作
SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作
SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第一个请求抵达
完成接收请求和回复……
SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作
SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第二个请求抵达
完成接收请求和回复……
SimpleReplyChannel.EndTryReceiveRequest() //重复
SimpleReplyChannel.BeginTryReceiveRequest() //重复
完成接收请求和回复……
SimpleReplyChannel.EndTryReceiveRequest() //重复
SimpleReplyChannel.BeginTryReceiveRequest() //重复
完成接收请求和回复……

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. directUI

    MFC界面开发中,习惯了使用控件,亦或者是自绘制控件来美化界面,但操作起来繁琐,还不太美观.DirectUI的出现,对于界面开发,给了我们一个新的选择,目前很多公司使用了该技术对其产品进行了美化,效果 ...

  2. Centos + nginx + JBOSS AS 7 搭建Java web application

    最近做了一个Java的web app,一直想在Centos环境中搭建一个完整的web服务器,现在开始动手. 先说说环境: 操作系统: Centos 6.3 WEB服务器: nginx-1.2.5 Ap ...

  3. ARM的STRB和LDRB指令分析

    一.SDRAM 1.存储结构 SDRAM的内部是一个存储阵列.阵列就如同表格一样,将数据“填”进去.在数据读写时和表格的检索原理一样,先指定一个行(Row),再指定一个列 (Column),我们就可以 ...

  4. DELPHI TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 控件分享

    仅供大家学习使用,请大家支持正版!! TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 该控件用来画图标,压缩包里还有FOR INTRAWEB的版本 链接: ...

  5. IOSアプリケーション開発環境の構築

    IOSアプリケーション開発環境の要求 1) IOSシステムの構造はそのようになっています: 2) ハードウエアの方の要求: コンピューター a)    デュアルコアCPU b)    8 gメモリ(開 ...

  6. BZOJ 3680 吊打XXX

    Description gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty.gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了.蒟蒻们将n个gty吊在n根绳子上,每根绳子穿过天台的一个洞 ...

  7. Reporting Services 钻取报表、子报表

    一.钻取报表 1.概念 钻取报表是指用户通过单击其他报表中的链接打开的报表.钻取报表通常包含某原始汇总报表中所包含的某项的详细信息. 例如,在此图中,销售额汇总报表列出了销售订单和总额.当用户单击该汇 ...

  8. %3A%2F%2F这样的叫什么码啊?

    %3A -> 3A -> 16*3+10 -> 58 -> chr(58) = ":"%2F -> 2F -> 16*2+15 -> 47 ...

  9. jQuery.extend方法和开发中变量的复用

    最近在用commonJS规范进行客户端开发,遇到如下问题: 一般一个模块内部可能会定义一系列变量或一系列相关变量,比如写了一个颜色选择弹框模块大概会有如下变量定义 var settings = { / ...

  10. SQL Server 2005/2008 触发器的管理和查看

    1.通过可视化操作来管理和查看触发器 在Microsoft SQL Server Management Studio中,选中某一数据库的某一张表时,在“对象资源管理器详细”窗口中有“触发器”项.通过“ ...