WCF - 绑定后续之自定义绑定
自定义信道基类
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 - 自定义绑定
自定义绑定 当系统提供的某个绑定不符合服务的要求时,可使用 CustomBinding 类.所有绑定都是从绑定元素的有序集构造而来的.自定义绑定可以从一组系统提供的绑定元素生成,也可以包含用户定义的自 ...
- WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(二)实现IRequestChannel(2016-03-15 12:35)
这是这个系列的第二篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...
- WCF 项目应用连载[8] - 绑定、服务、行为 大数据传输与限流 - 下 (ServiceThrottlingAttribute)
因为ORM的原因,对Attribute编程有一种情节..所以这节的出现,完全是因为在WCF对自定义Attribute的一种应用. WCF 项目应用连载[7] - 绑定.服务.行为 大数据传输与限流 - ...
- KNOCKOUTJS DOCUMENTATION-绑定(BINDINGS)-自定义绑定
除了ko内建的绑定,还可以自定义绑定,灵活地封装复杂的行为使之可重用. 自定义绑定 注册自定义绑定 向 ko.bindingHandles添加一个子属性来注册一个绑定. ko.bindingHandl ...
- Maven自定义绑定插件目标:创建项目的源码jar
<build> <plugins> <!-- 自定义绑定,创建项目的源码jar --> <plugin> <groupId>org.apac ...
- 背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换
[源码下载] 背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换 作者:webabcd 介 ...
- KnockoutJS 3.X API 第五章 高级应用(1) 创建自定义绑定
您不仅限于使用内置的绑定,如click,value绑定等,您可以创建自己的绑定. 这是如何控制视图模型如何与DOM元素进行交互,并且为您提供了大量的灵活性,以便于以复用的方式封装复杂的行为. 注册绑定 ...
- 5.Knockout.Js(自定义绑定)
前言 你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等).你可以你封装复杂的逻辑或行为,自定义很容易使用和重用的绑定.例如,你可以在form表单里自定义像grid ...
- 【Knockout】五、创建自定义绑定
概述 除了上一篇列出的KO内置的绑定类型(如value.text等),你也可以创建自定义绑定. 注册你的binding handler ko.bindingHandlers.yourBindingNa ...
随机推荐
- asp.net中的<%%>形式的详细用法实例讲解
asp.net中的代码分离模式我们肯定都不陌生,C#(或者其它语言)写的代码一般不会和设计语言HTML混在一起,但是有的时候也避免不了,这时就会在UI页面里用<%%>来绑定显示.绑定变量数 ...
- The largest prime factor(最大质因数)
1. 问题: The prime factors of 13195 are 5, 7, 13 and 29.What is the largest prime factor of the number ...
- Hadoop 2.6.0编译on mac
花了一个晚上的时间弄了下hadoop的编译环境,碰到些错误,这里保存下. 需要编译Hadoop,不但需要安装Maven,还需要安装protobuf 安装Maven 下载:apache-maven-3. ...
- linux tcp 好文
http://blog.csdn.net/htttw/article/details/7521053
- Web 研发模式演变
前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的优劣. 一.简单明快的早期时代 可称之为 Web 1.0 时代,非常适合创业型小项目,不分前后端,经常 ...
- JavaScript中url 传递参数(特殊字符)解决方法
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码 十六进制值1. + URL 中+号表示空格 %2B2. 空格 UR ...
- [UOJ 25] [IOI 2014] Wall 【线段树】
题目链接:UOJ - 25 题目分析 每个操作就是将被操作的数限制在一个区间,比如 Set_Max(5) 就是将被操作的数限定在了 [5, INF] 的区间里. 这些操作是可加的,但是必须按照顺序,不 ...
- [BZOJ 1143] [CTSC2008] 祭祀river 【最长反链】
题目链接:BZOJ - 1143 题目分析 这道题在BZOJ上只要求输出可选的最多的祭祀地点个数,是一道求最长反链长度的裸题. 下面给出一些相关知识: 在有向无环图中,有如下的一些定义和性质: 链:一 ...
- Java 比较两个字符串的大小
比较两个字符串的大小 static int compareTo(String s1, String s2) { int len1 = s1.length(); int len2 = s2.length ...
- innodb_buffer_pool_instances and innodb_buffer_pool_size的关系
把buffer pool 分成一个用户指定的单独的区域, 每个有它自己的LRU list和相关的数据结构, 降低竞争在并发内存读取和写操作. 这个选项只有当innodb_buffer_pool_siz ...