<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

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

      posted @ 2012-04-11 10:30  tyb1222  閱讀(3509)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 国产在线乱子伦一区二区| 99精品国产中文字幕| 内射一区二区三区四区| 69天堂人成无码免费视频| 中文字幕日韩人妻一区| 泸溪县| 老师破女学生处特级毛ooo片| 日韩人妻久久精品一区二区| 热久在线免费观看视频| 中文字幕精品亚洲二区| 青青草久热这里只有精品| 九九成人免费视频| 国产一区| 男女爽爽无遮挡午夜视频| 精品无码久久久久国产电影| 无码一区二区三区久久精品| 午夜成人性爽爽免费视频| 乱人伦人妻中文字幕| 一色桃子中出欲求不满人妻| 欧美老少配性行为| 国产黄色一区二区三区四区| 日韩人妻无码一区二区三区99| 成人天堂资源www在线| 无码av天天av天天爽| 成在人线AV无码免观看| 99久久久国产精品免费无卡顿| 夜夜春久久天堂亚洲精品| 国产精品大片中文字幕| 欧美和黑人xxxx猛交视频| 国产亚洲精品aaaa片app| 少妇人妻88久久中文字幕| 久久夜色国产噜噜亚洲av| 特级av毛片免费观看| 久热这里只有精品蜜臀av | 欧美国产精品不卡在线观看| 三上悠亚精品一区二区久久| 色综合久久综合中文综合网| 免费国产一级 片内射老| 亚洲欧美在线观看品| 昌吉市| 无套内谢少妇高清毛片|