WCF之“HelloWorld”(三)
上两篇中我们看到了两个Solution,第一个为正规的WCF应用程序(可以在第一篇文章中下载源代码),有契约,有配置文件,有服务端宿主,有客户端。而第二个Solution(可以在第二篇中下载源代码)是个精简版的WCF程序,只有两个Console应用程序。一个充当服务端,一个充当客户端。我们来分析一下两个Solution。
先从第二个Solution开始:
在服务端,我们首先创建了一个binding对象--->由这个binding对象得到了个ChannelListener--->由这个ChennelListener负责创建出具体的Channel--->最后用这个Channel接收客户端请求并给客户端返回结果。由此我们可以得到这样一个结论:
Binding--->ChannelListener--->Channel
对照代码为:
BasicHttpBinding serverBinding = new BasicHttpBinding();--->
IChannelListener<IReplyChannel> listener = serverBinding.BuildChannelListener<IReplyChannel>(uri);--->
IReplyChannel channel = listener.AcceptChannel();
在客户端,同样第一步也是创建了一个binding对象--->由此binding对象创建ChannelFactory--->由此ChannelFactory创建Channel--->由此Chennel发送客户端请求。同样我们得到如下结论:
Binding--->ChannelFactory--->Chennel
对照代码为:
BasicHttpBinding clientBinding = new BasicHttpBinding();---->
IChannelFactory<IRequestChannel> factory = clientBinding.BuildChannelFactory<IRequestChannel>();--->
IRequestChannel clientChannel = factory.CreateChannel(myEndPoint);
关于Channel Sharp(代码中红色标示部分)我们以后再说。
再来看看第一个Solution:
我们从Host着手,通过Reflector反射代码。来看看它是如何褪去身上一层层神秘面纱的。
ServiceHost host = new ServiceHost(typeof(MyService))
1.首先构造ServiceHost 类型的对象。从元数据我知道ServiceHost 是继承自ServiceHostBase
public class ServiceHost : ServiceHostBase
{}
从而ServiceHost 类继承了ServiceHostBase的所有方法。其中有一个open方法。
2.所以接下来调用ServiceHost 的Open()方法。
host.Open();
调用Open方法会触发OnOpen方法。
我们看看OnOpen方法干了什么:(反射出来的代码)
for (int i = 0; i < this.ChannelDispatchers.Count; i++)
{
this.ChannelDispatchers[i].Open(helper.RemainingTime());
}
原来OnOpen会调用ChennelDispatcher的Open方法。这里又多出一个东西。ChannelDispatcher,以后再说这个对象。继续追踪看看ChannelDispatcher的Open方法又干了什么?
if (this.listener != null)
{
try
{
this.listener.Open(timeout);
}
catch (InvalidOperationException exception)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.CreateOuterExceptionWithEndpointsInformation(exception));
}
}
原来它又调用了ChannelListener的Open方法。ChannelListener大家应该有印象了。到这步我想应该很明白了吧,后面的步骤就和第二个Solution一样了,其实后面还有很多有趣的东西。这里就不一步一步往下追了。有兴趣的可以通过Reflecter去反射出代码。总结一下第一个Solution的执行过程:
ServiceHost--->Open()---->ChannelDispatcher--->Open()--->ChennelListener--->Open()--->AcceptChennel()