Fork me on GitHub
深入理解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 on 2012-04-11 22:35  HackerVirus  阅读(262)  评论(0编辑  收藏  举报