好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

深入理解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中,定义:

private readonly  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,  0 ,  true );
    }
StackBuilderSink中SyncProcessMessage的处理过程:
         public   virtual  IMessage SyncProcessMessage(IMessage msg)
    {
         return   this .SyncProcessMessage(msg,  0 ,  false );
    }

         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,  null ,  0 , 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客户端流程如下图:

 

上图流程说明:

       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关系图描述一下这些类型之间的关系:

 

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

 4.3、ServiceChannel生成时序图

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

 

 

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

分类:  WCF架构体系

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于深入理解WCF系统体系(之二:WCF客户端如何构建?(下))的详细内容...

  阅读:40次