深入理解WCF系统体系(之二:WCF客户端如何构建?(下))

前一节介绍了WCF客户端构建的过程,其间又说明了WCF框架中核心ClientRuntime对象建立过程,以及客户端所采用的ClientMessageInspectors、ClientMessageFormatter、ClientOperationSelector等等基础。

 

 

本节目录:
1、RealProxy建立的过程
2、TransparentProxy建立的过程
3、服务调用过程。

4、总结 

 

 
1、RealProxy建立的过程
 

通过之前的介绍,大家都应该有个共识:客户端通过透明代理建立对应的实际代理对服务进行调用,而在WCF在实际代理对象类型为ServiceChannelProxy。实际代理对象ServiceChannelProxy的建立又是通过它的构造函数完成。先来看看它的构造函数:

 

  internal ServiceChannelProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel) :  base(proxiedType)
    {
         if (!MessageDirectionHelper.IsDefined(direction))
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ArgumentOutOfRangeException( " direction "));
        }
         this.interfaceType = interfaceType;
         this.proxiedType = proxiedType;
         this.serviceChannel = serviceChannel;
         this.proxyRuntime = serviceChannel.ClientRuntime.GetRuntime();
         this.methodDataCache =  new MethodDataCache();
         this.objectWrapper =  new MbrObject( this, proxiedType);

    } 

 

在WCF客户端中,ChannelFactory通过绑定创建; 在  ChannelFactory创建的过程中,会初始化ServiceEndpoint;通过ServiceEndpoint又创建ServiceChannelFactory;通过ServiceChannelFactory

创建ServiceChannel。而ServiceChannelProxy接口中的Type类型就是契约接口类型,MessageDirection

是一个枚举类型,有Input\Output两个枚举值。这些类型,真实代理对象就创建成功。

通过以上述过程,真实代理对象就创建成功。

 
2、TransparentProxy建立的过程
 

首先看看一下代码:

 

var instanceContext =  new InstanceContext( new CalculatorCallback());
using ( var channkeFactory =  new DuplexChannelFactory<ICalculator>(instanceContext, " calculator "))
{                
    ICalculator proxy = channkeFactory.CreateChannel();        
}
通过上节的分析,通过channkeFactory.CreateChannel()得到的proxy就是TransparentProxy对象。那么channkeFactory通过CreateChannel创建TransparentProxy对象都经过了那些过程呢。?要了解这个过程,还得从源

码分析得出:

public  class DuplexChannelFactory<TChannel> : ChannelFactory<TChannel>
{
     public TChannel CreateChannel(InstanceContext callbackInstance)
    {
          return  this.CreateChannel(callbackInstance,  base.CreateEndpointAddress( base.Endpoint),  null);
    }

     public  static TChannel CreateChannel( object callbackObject,  string endpointConfigurationName)
    {
         return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), endpointConfigurationName);
    }

     public  override TChannel CreateChannel(EndpointAddress address, Uri via)
    {
         return  this.CreateChannel( base.CallbackInstance, address, via);
    }

     public TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address)
    {
         if (address ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address ");
        }
         return  this.CreateChannel(callbackInstance, address, address.Uri);
    }

     public  static TChannel CreateChannel(InstanceContext callbackInstance,  string endpointConfigurationName)
    {
        TChannel channel =  new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName).CreateChannel();
        ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
         return channel;
    }

     public  static TChannel CreateChannel( object callbackObject, Binding binding, EndpointAddress endpointAddress)
    {
         return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), binding, endpointAddress);
    }

     public  static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress)
    {
        TChannel channel =  new DuplexChannelFactory<TChannel>(callbackInstance, binding, endpointAddress).CreateChannel();
        ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
         return channel;
    }

     public  virtual TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address, Uri via)
    {
         if (address ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address ");
        }
         if (( base.CallbackType !=  null) && (callbackInstance ==  null))
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallback1 ")));
        }
         if (callbackInstance ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallback ")));
        }
         if (callbackInstance.UserObject ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallbackUserObject ")));
        }
         if (! base.HasDuplexOperations())
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannel1 "new  object[] {  base.Endpoint.Contract.Name })));
        }
        Type c = callbackInstance.UserObject.GetType();
        Type callbackContractType =  base.Endpoint.Contract.CallbackContractType;
         if ((callbackContractType !=  null) && !callbackContractType.IsAssignableFrom(c))
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelBadCallbackUserObject "new  object[] { callbackContractType })));
        }
         base.EnsureOpened();
        TChannel local = (TChannel)  base.ServiceChannelFactory.CreateChannel( typeof(TChannel), address, via);
        IDuplexContextChannel channel = local  as IDuplexContextChannel;
         if (channel !=  null)
        {
            channel.CallbackInstance = callbackInstance;
        }
         return local;
    }

     public  static TChannel CreateChannel( object callbackObject, Binding binding, EndpointAddress endpointAddress, Uri via)
    {
         return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), binding, endpointAddress, via);
    }

     public  static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress, Uri via)
    {
        TChannel channel =  new DuplexChannelFactory<TChannel>(callbackInstance, binding).CreateChannel(endpointAddress, via);
        ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
         return channel;
    }

}
查看以上代码,我们发现DuplexChannelFactory<TChannel>类的CreateChannel()方法中没有不带参数的,那它通过CreateChannel()方法创建TransparentProxy时,肯定是调用了基类的方法。
接下去分析ChannelFactory<TChannel>的CreateChannel方法。代码如下:
public  class ChannelFactory<TChannel> : ChannelFactory, IChannelFactory<TChannel>, IChannelFactory, ICommunicationObject
{
     public TChannel CreateChannel()
    {
         return  this.CreateChannel( base.CreateEndpointAddress( base.Endpoint),  null);
    }
     public  virtual TChannel CreateChannel(EndpointAddress address, Uri via)
    {
        TChannel local;
         bool traceOpenAndClose =  base.TraceOpenAndClose;
         try
        {
             using (ServiceModelActivity activity = (DiagnosticUtility.ShouldUseActivity &&  base.TraceOpenAndClose) ? ServiceModelActivity.CreateBoundedActivity() :  null)
            {
                 if (DiagnosticUtility.ShouldUseActivity)
                {
                    ServiceModelActivity.Start(activity,  this.OpenActivityName,  this.OpenActivityType);
                     base.TraceOpenAndClose =  false;
                }
                 if (address ==  null)
                {
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address ");
                }
                 if ( base.HasDuplexOperations())
                {
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateNonDuplexChannel1 "new  object[] {  base.Endpoint.Contract.Name })));
                }
                 base.EnsureOpened();
                local = (TChannel)  this.ServiceChannelFactory.CreateChannel( typeof(TChannel), address, via);
            }
        }
         finally
        {
             base.TraceOpenAndClose = traceOpenAndClose;
        }
         return local;
    }
}
 

注意到这一句:

local = (TChannel) this.ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via);

继续分析ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via)的过程:

internal  abstract  class ServiceChannelFactory : ChannelFactoryBase
{
     public  object CreateChannel(Type channelType, EndpointAddress address, Uri via)
    {
         if (via ==  null)
        {
            via =  this.ClientRuntime.Via;
             if (via ==  null)
            {
                via = address.Uri;
            }
        }
        ServiceChannel serviceChannel =  this.CreateServiceChannel(address, via);
        serviceChannel.Proxy = CreateProxy(channelType, channelType, MessageDirection.Input, serviceChannel);
        serviceChannel.ClientRuntime.GetRuntime().InitializeChannel((IClientChannel) serviceChannel.Proxy);
        OperationContext current = OperationContext.Current;
         if ((current !=  null) && (current.InstanceContext !=  null))
        {
            current.InstanceContext.WmiChannels.Add((IChannel) serviceChannel.Proxy);
            serviceChannel.WmiInstanceContext = current.InstanceContext;
        }
         return serviceChannel.Proxy;
    }

        [SecuritySafeCritical]
     internal  static  object CreateProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel)
    {
      if (!proxiedType.IsInterface)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxChannelFactoryTypeMustBeInterface ")));
        }
        ServiceChannelProxy proxy =  new ServiceChannelProxy(interfaceType, proxiedType, direction, serviceChannel);
         return proxy.GetTransparentProxy();
    }
}
 

CreateChannel方法返回的是serviceChannel.Proxy,而serviceChannel.Proxy又是

proxy.GetTransparentProxy()获取到的TransparentProxy.

 
3、服务调用过程。
WCF客户端对服务接口的调用最终通过RealProxy对象,也就是ServiceChannelProxy的Invoke方法来完成。

下面来看看Invoke方法。

  public  override IMessage Invoke(IMessage message)
    {
        IMessage message3;
         try
        {
            IMethodCallMessage methodCall = message  as IMethodCallMessage;
             if (methodCall ==  null)
            {
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ArgumentException(SR.GetString( " SFxExpectedIMethodCallMessage ")));
            }
            MethodData methodData =  this.GetMethodData(methodCall);
             switch (methodData.MethodType)
            {
                 case MethodType.Service:
                     return  this.InvokeService(methodCall, methodData.Operation);

                 case MethodType.BeginService:
                     return  this.InvokeBeginService(methodCall, methodData.Operation);

                 case MethodType.EndService:
                     return  this.InvokeEndService(methodCall, methodData.Operation);

                 case MethodType.Channel:
                     return  this.InvokeChannel(methodCall);

                 case MethodType.Object:
                     return  this.InvokeObject(methodCall);

                 case MethodType.GetType:
                     return  this.InvokeGetType(methodCall);
            }
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( string.Format(CultureInfo.InvariantCulture,  " Invalid proxy method type "new  object[ 0])));
        }
         catch (Exception exception)
        {
             if (Fx.IsFatal(exception))
            {
                 throw;
            }
            message3 =  this.CreateReturnMessage(exception, message  as IMethodCallMessage);
        }
         return message3;
    }
 
 

 

3.1、MethodData的Service类型

 

MethodType.Service为同步调用方式;MethodType.BeginService、MethodType.EndService为异步方式。

首先看看MethodType.Service,它调用了ServiceChannelProxy的InvokeService方法完成。InvokeService方法定义如下:

     private IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
    {
         object[] objArray;
         object[] ins = operation.MapSyncInputs(methodCall,  out objArray);
         object ret =  this.serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, objArray);
         object[] returnArgs = operation.MapSyncOutputs(methodCall, objArray,  ref ret);
         return  this.CreateReturnMessage(ret, returnArgs, methodCall);
    }
 

可以看出,在  InvokeService中,通过serviceChannel.Call返回调用结果,最有又通过ServerChannelProxy的

CreateReturnMessage方法返回Message。

ProxyOperationRuntime在WCF中也是很重要的对象。它的定义以及构造函数如下:

internal  class ProxyOperationRuntime
{
     //  Fields
     private  string action;
     private MethodInfo beginMethod;
     private  bool deserializeReply;
     internal  static  readonly  object[] EmptyArray =  new  object[ 0];
     private ParameterInfo[] endOutParams;
     private  readonly IClientFaultFormatter faultFormatter;
     private  readonly IClientMessageFormatter formatter;
     private ParameterInfo[] inParams;
     private  readonly  bool isInitiating;
     private  readonly  bool isOneWay;
     private  readonly  bool isTerminating;
     private  readonly  string name;
     internal  static  readonly ParameterInfo[] NoParams =  new ParameterInfo[ 0];
     private ParameterInfo[] outParams;
     private  readonly IParameterInspector[] parameterInspectors;
     private  readonly ImmutableClientRuntime parent;
     private  string replyAction;
     private ParameterInfo returnParam;
     private  bool serializeRequest;
     private MethodInfo syncMethod;

     //  Methods
     internal ProxyOperationRuntime(ClientOperation operation, ImmutableClientRuntime parent)
    {
         if (operation ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " operation ");
        }
         if (parent ==  null)
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " parent ");
        }
         this.parent = parent;
         this.formatter = operation.Formatter;
         this.isInitiating = operation.IsInitiating;
         this.isOneWay = operation.IsOneWay;
         this.isTerminating = operation.IsTerminating;
         this.name = operation.Name;
         this.parameterInspectors = EmptyArray<IParameterInspector>.ToArray(operation.ParameterInspectors);
         this.faultFormatter = operation.FaultFormatter;
         this.serializeRequest = operation.SerializeRequest;
         this.deserializeReply = operation.DeserializeReply;
         this.action = operation.Action;
         this.replyAction = operation.ReplyAction;
         this.beginMethod = operation.BeginMethod;
         this.syncMethod = operation.SyncMethod;
         if ( this.beginMethod !=  null)
        {
             this.inParams = ServiceReflector.GetInputParameters( this.beginMethod,  true);
             if ( this.syncMethod !=  null)
            {
                 this.outParams = ServiceReflector.GetOutputParameters( this.syncMethod,  false);
            }
             else
            {
                 this.outParams = NoParams;
            }
             this.endOutParams = ServiceReflector.GetOutputParameters(operation.EndMethod,  true);
             this.returnParam = operation.EndMethod.ReturnParameter;
        }
         else  if ( this.syncMethod !=  null)
        {
             this.inParams = ServiceReflector.GetInputParameters( this.syncMethod,  false);
             this.outParams = ServiceReflector.GetOutputParameters( this.syncMethod,  false);
             this.returnParam =  this.syncMethod.ReturnParameter;
        }
         if (( this.formatter ==  null) && ( this.serializeRequest ||  this.deserializeReply))
        {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " ClientRuntimeRequiresFormatter0 "new  object[] {  this.name })));
        }
    }

    [SecurityCritical]
     internal  object[] MapSyncInputs(IMethodCallMessage methodCall,  out  object[] outs)
    {
         if ( this.outParams.Length ==  0)
        {
            outs = EmptyArray;
        }
         else
        {
            outs =  new  object[ this.outParams.Length];
        }
         if ( this.inParams.Length ==  0)
        {
             return EmptyArray;
        }
         return methodCall.InArgs;
    }

        [SecurityCritical]
     internal  object[] MapSyncOutputs(IMethodCallMessage methodCall,  object[] outs,  ref  object ret)
    {
         return  this.MapOutputs( this.outParams, methodCall, outs,  ref ret);
    }

        [SecurityCritical]
     private  object[] MapOutputs(ParameterInfo[] parameters, IMethodCallMessage methodCall,  object[] outs,  ref  object ret)
    {
         if ((ret ==  null) && ( this.returnParam !=  null))
        {
            ret = GetDefaultParameterValue(TypeLoader.GetParameterType( this.returnParam));
        }
         if (parameters.Length ==  0)
        {
             return  null;
        }
         object[] args = methodCall.Args;
         for ( int i =  0; i < parameters.Length; i++)
        {
             if (outs[i] ==  null)
            {
                args[parameters[i].Position] = GetDefaultParameterValue(TypeLoader.GetParameterType(parameters[i]));
            }
             else
            {
                args[parameters[i].Position] = outs[i];
            }
        }
         return args;
    }

    /
    ****/
 }
 

IMethodCallMessage的InArgs:获取未标记为 out 参数的参数数组;Args:获取传递给该方法的参数数组(MSDN中的定义)。

 
那么最核心的ServiceChannel的Call方法又做了什么事情呢。。?让我们看看它的定义:
internal  object Call( string action,  bool oneway, ProxyOperationRuntime operation,  object[] ins,  object[] outs)
    {
         return  this.Call(action, oneway, operation, ins, outs,  this.operationTimeout);
    }

     internal  object Call( string action,  bool oneway, ProxyOperationRuntime operation,  object[] ins,  object[] outs, TimeSpan timeout)
    {
         this.ThrowIfDisallowedInitializationUI();
         this.ThrowIfIdleAborted(operation);
        ProxyRpc rpc =  new ProxyRpc( this, operation, action, ins, timeout);
         using (rpc.Activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() :  null)
        {
             if (DiagnosticUtility.ShouldUseActivity)
            {
                ServiceModelActivity.Start(rpc.Activity, SR.GetString( " ActivityProcessAction "new  object[] { action }), ActivityType.ProcessAction);
            }
             this.PrepareCall(operation, oneway,  ref rpc);
             if (! this.explicitlyOpened)
            {
                 this.EnsureDisplayUI();
                 this.EnsureOpened(rpc.TimeoutHelper.RemainingTime());
            }
             else
            {
                 this.ThrowIfOpening();
                 base.ThrowIfDisposedOrNotOpen();
            }
             try
            {
                ConcurrencyBehavior.UnlockInstanceBeforeCallout(OperationContext.Current);
                 if (oneway)
                {
                     this.binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
                }
                 else
                {
                    rpc.Reply =  this.binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime());
                     if (rpc.Reply ==  null)
                    {
                         base.ThrowIfFaulted();
                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new CommunicationException(SR.GetString( " SFxServerDidNotReply ")));
                    }
                }
            }
             finally
            {
                 this.CompletedIOOperation();
                CallOnceManager.SignalNextIfNonNull( this.autoOpenManager);
                ConcurrencyBehavior.LockInstanceAfterCallout(OperationContext.Current);
            }
            rpc.OutputParameters = outs;
             this.HandleReply(operation,  ref rpc);
        }
         return rpc.ReturnValue;

上面代码中有至关重要的一段:

 
if (oneway) 

                {
                    this.binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
                }
                else
                {
                    rpc.Reply = this.binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime());
         }

  

 通过是否单程oneway,来进行Send或者Request。那binder由是什么对象呢。。?

在ServiceChannel中,定义:

privatereadonly IChannelBinder binder。这点可以从RealProxy对象中可以看出来:

 

 

在本例中使用netTcpBinding绑定,所以binder为DuplexChannelBinder。不同的协议类型,

binder就不一样。以wsHttpBinding为例,它的binder为RequestChannelBinder。

 

 DuplexChannelBinder的Send与Request定义如下:

 
       public  void Send(Message message, TimeSpan timeout) 

      {
        this.channel.Send(message, timeout);
      }

     public Message Request(Message message, TimeSpan timeout)
     {
        SyncDuplexRequest request = null;
        bool flag = false;
        RequestReplyCorrelator.PrepareRequest(message);
        lock (this.ThisLock)
        {
            if (!this.Pumping)
            {
                flag = true;
                this.syncPumpEnabled = true;
            }
            if (!flag)
            {
                request = new SyncDuplexRequest(this);
            }
            this.RequestStarting(message, request);
        }
        if (flag)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);
            UniqueId messageId = message.Headers.MessageId;
            try
            {
                this.channel.Send(message, helper.RemainingTime());
                if ((DiagnosticUtility.ShouldUseActivity && (ServiceModelActivity.Current != null)) && (ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction))
                {
                    ServiceModelActivity.Current.Suspend();
                }
                while (true)
                {
                    Message message2;
                    do
                    {
                        TimeSpan span = helper.RemainingTime();
                        if (!this.channel.TryReceive(span, out message2))
                        {
                            throw TraceUtility.ThrowHelperError(this.GetReceiveTimeoutException(timeout), message);
                        }
                        if (message2 == null)
                        {
                            this.AbortRequests();
                            return null;
                        }
                        if (message2.Headers.RelatesTo == messageId)
                        {
                            this.ThrowIfInvalidReplyIdentity(message2);
                            return message2;
                        }
                    }
                    while (this.HandleRequestAsReply(message2));
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        EndpointDispatcher endpointDispatcher = null;
                        if ((this.ChannelHandler != null) && (this.ChannelHandler.Channel != null))
                        {
                            endpointDispatcher = this.ChannelHandler.Channel.EndpointDispatcher;
                        }
                        TraceUtility.TraceDroppedMessage(message2, endpointDispatcher);
                    }
                    message2.Close();
                }
            }
            finally
            {
                lock (this.ThisLock)
                {
                    this.RequestCompleting(null);
                    this.syncPumpEnabled = false;
                    if (this.pending > 0)
                    {
                        this.EnsurePumping();
                    }
                }
            }
        }
    TimeoutHelper helper2 = new TimeoutHelper(timeout);
        this.channel.Send(message, helper2.RemainingTime());
        this.EnsurePumping();
        return request.WaitForReply(helper2.RemainingTime());
    }

 

在Request中,除了调用Channel的Send方法以外,还调用了SyncDuplexRequest的WaitForReply返回消息。

SyncDuplexRequest的WaitForReply定义如下:

 

    
     internal Message WaitForReply(TimeSpan timeout)

    {
        try
        {
            if (!TimeoutHelper.WaitOne(this.wait, timeout))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.parent.GetReceiveTimeoutException(timeout));
            }
        }
        finally
        {
            this.CloseWaitHandle();
        }
        this.parent.ThrowIfInvalidReplyIdentity(this.reply);
        return this.reply;
    }

 
 

3.2MethodData的Channel类型:

 

  private IMethodReturnMessage InvokeChannel(IMethodCallMessage methodCall)
    {
         string str =  null;
        ActivityType unknown = ActivityType.Unknown;
         if (DiagnosticUtility.ShouldUseActivity && ((ServiceModelActivity.Current ==  null) || (ServiceModelActivity.Current.ActivityType != ActivityType.Close)))
        {
            MethodData methodData =  this.GetMethodData(methodCall);
             if ((methodData.MethodBase.DeclaringType ==  typeof(ICommunicationObject)) && methodData.MethodBase.Name.Equals( " Close ", StringComparison.Ordinal))
            {
                str = SR.GetString( " ActivityClose "new  object[] {  this.serviceChannel.GetType().FullName });
                unknown = ActivityType.Close;
            }
        }
         using (ServiceModelActivity activity =  string.IsNullOrEmpty(str) ?  null : ServiceModelActivity.CreateBoundedActivity())
        {
             if (DiagnosticUtility.ShouldUseActivity)
            {
                ServiceModelActivity.Start(activity, str, unknown);
            }
             return  this.ExecuteMessage( this.serviceChannel, methodCall);
        }
    }

         private IMethodReturnMessage ExecuteMessage( object target, IMethodCallMessage methodCall)
    {
        MethodBase methodBase = methodCall.MethodBase;
         object[] args = methodCall.Args;
         object ret =  null;
         try
        {
            ret = methodBase.Invoke(target, args);
        }
         catch (TargetInvocationException exception)
        {
             return  this.CreateReturnMessage(exception.InnerException, methodCall);
        }
         return  this.CreateReturnMessage(ret, args, args.Length,  null, methodCall);
    }

 

对于Channel,直接调用methodBase.Invoke进行调用

 
 

3.3、MethodData的Object类型

 

private IMethodReturnMessage InvokeObject(IMethodCallMessage methodCall)
    {
         return RemotingServices.ExecuteMessage( this.objectWrapper, methodCall);
    }
RemotingServices中ExecuteMessage的定义如下:
    [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
     public  static IMethodReturnMessage ExecuteMessage(MarshalByRefObject target, IMethodCallMessage reqMsg)
    {
         if (target ==  null)
        {
             throw  new ArgumentNullException( " target ");
        }
        RealProxy realProxy = GetRealProxy(target);
         if ((realProxy  is RemotingProxy) && !realProxy.DoContextsMatch())
        {
             throw  new RemotingException(Environment.GetResourceString( " Remoting_Proxy_WrongContext "));
        }
        StackBuilderSink sink =  new StackBuilderSink(target);
         return (IMethodReturnMessage) sink.SyncProcessMessage(reqMsg,  0true);
    }
StackBuilderSink中SyncProcessMessage的处理过程:
         public  virtual IMessage SyncProcessMessage(IMessage msg)
    {
         return  this.SyncProcessMessage(msg,  0false);
    }

         internal  virtual IMessage SyncProcessMessage(IMessage msg,  int methodPtr,  bool fExecuteInContext)
    {
        IMessage message3;
        IMessage message = InternalSink.ValidateMessage(msg);
         if (message !=  null)
        {
             return message;
        }
        IMethodCallMessage message2 = msg  as IMethodCallMessage;
        LogicalCallContext threadCallContext =  null;
         object obj2 = CallContext.GetLogicalCallContext().GetData( " __xADCall ");
         bool flag =  false;
         try
        {
             object server =  this._server;
            VerifyIsOkToCallMethod(server, message2);
            LogicalCallContext callCtx =  null;
             if (message2 !=  null)
            {
                callCtx = message2.LogicalCallContext;
            }
             else
            {
                callCtx = (LogicalCallContext) msg.Properties[ " __CallContext "];
            }
            threadCallContext = CallContext.SetLogicalCallContext(callCtx);
            flag =  true;
            callCtx.PropagateIncomingHeadersToCallContext(msg);
            PreserveThreadPrincipalIfNecessary(callCtx, threadCallContext);
             if ( this.IsOKToStackBlt(message2, server) && ((Message) message2).Dispatch(server, fExecuteInContext))
            {
                message3 =  new StackBasedReturnMessage();
                ((StackBasedReturnMessage) message3).InitFields((Message) message2);
                LogicalCallContext context4 = CallContext.GetLogicalCallContext();
                context4.PropagateOutgoingHeadersToMessage(message3);
                ((StackBasedReturnMessage) message3).SetLogicalCallContext(context4);
                 return message3;
            }
            MethodBase methodBase = GetMethodBase(message2);
             object[] outArgs =  null;
             object ret =  null;
            RemotingMethodCachedData reflectionCachedData = InternalRemotingServices.GetReflectionCachedData(methodBase);
             object[] args = Message.CoerceArgs(message2, reflectionCachedData.Parameters);
            ret =  this.PrivateProcessMessage(methodBase.MethodHandle, args, server, methodPtr, fExecuteInContext,  out outArgs);
             this.CopyNonByrefOutArgsFromOriginalArgs(reflectionCachedData, args,  ref outArgs);
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
             if (((obj2 !=  null) && (( bool) obj2)) && (logicalCallContext !=  null))
            {
                logicalCallContext.RemovePrincipalIfNotSerializable();
            }
            message3 =  new ReturnMessage(ret, outArgs, (outArgs ==  null) ?  0 : outArgs.Length, logicalCallContext, message2);
            logicalCallContext.PropagateOutgoingHeadersToMessage(message3);
            CallContext.SetLogicalCallContext(threadCallContext);
        }
         catch (Exception exception)
        {
            message3 =  new ReturnMessage(exception, message2);
            ((ReturnMessage) message3).SetLogicalCallContext(message2.LogicalCallContext);
             if (flag)
            {
                CallContext.SetLogicalCallContext(threadCallContext);
            }
        }
         return message3;

 

 

3.4MethodData的GetType类型

 

private IMethodReturnMessage InvokeGetType(IMethodCallMessage methodCall)
    {
         return  this.CreateReturnMessage( this.proxiedType,  null0, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
    }
      private IMethodReturnMessage CreateReturnMessage( object ret,  object[] outArgs,  int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
    {
         return  new ReturnMessage(ret, outArgs, outArgsCount, callCtx, mcm);
    }

 

它调用了ReturnMessage的如下构造函数:

 

   public ReturnMessage( object ret,  object[] outArgs,  int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)   

 {
        this._ret = ret;
        this._outArgs = outArgs;
        this._outArgsCount = outArgsCount;
        if (callCtx != null)
        {
            this._callContext = callCtx;
        }
        else
        {
            this._callContext = CallContext.GetLogicalCallContext();
        }
        if (mcm != null)
        {
            this._URI = mcm.Uri;
            this._methodName = mcm.MethodName;
            this._methodSignature = null;
            this._typeName = mcm.TypeName;
            this._hasVarArgs = mcm.HasVarArgs;
            this._methodBase = mcm.MethodBase;
        }
    }

 

4、总结:

  WCF的客户端框架中介绍了很多MS封装的内部对象,整个流程的说明介绍这些对象时根据流程的介绍的需要进行

了一些介绍。下面对这些对象做个总结以认清它们之间的关系。

4.1、WCF客户端流程:

WCF客户端流程如下图:

深入理解WCF系统体系(之二:WCF客户端如何构建?(下))_第1张图片 

上图流程说明:

    1、由DuplexChannelFactory的父类:ChannelFactory<TChannel>的父类ChannelFactory初始化

Endpoint。

 2、ChannelFactory调用ServiceChannelFactroy的BuildChannelFactory,通过初始化的Endpoint创建

ServiceChannelFactroy。(根据契约需要的通道形状,会生成继承自ServiceChannelFactory的

ServiceChannelFactoryOverX,)

   3、ServiceChannelFactroy创建ServiceChannelFactroy的过程中,会初始化ClientRuntime对象
    4、ServiceChannelFactoryOverX通过CreateInnerChannelBinder创建IChannelBinder对象。
   5、ServiceChannelFactoryOverX通过CreateInnerChannelBinder方法创建IChannelBinder对象
   6、ServiceChannelFactoryOverX通过CreateChannel创建ServiceChannel,并通过ImmutableClientRuntime初始化Channel。
   7、实际代理ServiceChannelProxy 通过ServiceChannel对象,契约接口定义生成RealProxy。
   8、通过RealProxy获取TransparentProxy对象
   9、TransparentProxy对象调用服务
   10、ServiceChannel通过IChannelBinder对象发送消息
 

4.2、WCF客户端使用到的对象关系

在这两节分析WCF客户端时,介绍了很多内部 对象。通过UML关系图描述一下这些类型之间的关系:

深入理解WCF系统体系(之二:WCF客户端如何构建?(下))_第2张图片 

在上图中,以接口为分界线,上半部分生成ServiceChannel;下半部分生成调用服务的代理。 

 4.3、ServiceChannel生成时序图

最后后通过时序图介绍一下ServiceChannel、IChannelBinder对象生成过程:

深入理解WCF系统体系(之二:WCF客户端如何构建?(下))_第3张图片 

 

备注:本节以及前一节中所有流程的说明都是以netTcpBiding作为传输协议来进行的,其他协议也类似。

分类:  WCF架构体系

你可能感兴趣的:(WCF)