深入理解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客戶端流程如下圖:

 

上圖流程說明:

    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作為傳輸協議來進行的,其他協議也類似。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM