深入理解WCF系统体系(之二:WCF客户端如何构建?(下))
前一节 介绍了WCF客户端构建的过程,其间又说明了WCF框架中核心ClientRuntime对象建立过程,以及客户端所采用的ClientMessageInspectors、ClientMessageFormatter、ClientOperationSelector等等基础。
本节目录:
1、RealProxy建立的过程
2、TransparentProxy建立的过程
3、服务调用过程。
4、总结
1、RealProxy建立的过程
通过之前的介绍,大家都应该有个共识:客户端通过透明代理建立对应的实际代理对服务进行调用,而在WCF在实际代理对象类型为ServiceChannelProxy。实际代理对象ServiceChannelProxy的建立又是通过它的构造函数完成。先来看看它的构造函数:
internal ServiceChannelProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel) : base (proxiedType)
{
if (!MessageDirectionHelper.IsDefined(direction))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ArgumentOutOfRangeException( " direction " ));
}
this .interfaceType = interfaceType;
this .proxiedType = proxiedType;
this .serviceChannel = serviceChannel;
this .proxyRuntime = serviceChannel.ClientRuntime.GetRuntime();
this .methodDataCache = new MethodDataCache();
this .objectWrapper = new MbrObject( this , proxiedType);
}
在WCF客户端中,ChannelFactory通过绑定创建; 在 ChannelFactory创建的过程中,会初始化ServiceEndpoint;通过ServiceEndpoint又创建ServiceChannelFactory;通过ServiceChannelFactory
创建ServiceChannel。而ServiceChannelProxy接口中的Type类型就是契约接口类型,MessageDirection
是一个枚举类型,有Input\Output两个枚举值。这些类型,真实代理对象就创建成功。
通过以上述过程,真实代理对象就创建成功。
2、TransparentProxy建立的过程
首先看看一下代码:
var instanceContext = new InstanceContext( new CalculatorCallback());
using ( var channkeFactory = new DuplexChannelFactory<ICalculator>(instanceContext, " calculator " ))
{
ICalculator proxy = channkeFactory.CreateChannel();
}
通过上节的分析,通过channkeFactory.CreateChannel()得到的proxy就是TransparentProxy对象。那么channkeFactory通过CreateChannel创建TransparentProxy对象都经过了那些过程呢。?要了解这个过程,还得从源
码分析得出:
public class DuplexChannelFactory<TChannel> : ChannelFactory<TChannel>
{
public TChannel CreateChannel(InstanceContext callbackInstance)
{
return this .CreateChannel(callbackInstance, base .CreateEndpointAddress( base .Endpoint), null );
}
public static TChannel CreateChannel( object callbackObject, string endpointConfigurationName)
{
return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), endpointConfigurationName);
}
public override TChannel CreateChannel(EndpointAddress address, Uri via)
{
return this .CreateChannel( base .CallbackInstance, address, via);
}
public TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address)
{
if (address == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address " );
}
return this .CreateChannel(callbackInstance, address, address.Uri);
}
public static TChannel CreateChannel(InstanceContext callbackInstance, string endpointConfigurationName)
{
TChannel channel = new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName).CreateChannel();
ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
return channel;
}
public static TChannel CreateChannel( object callbackObject, Binding binding, EndpointAddress endpointAddress)
{
return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), binding, endpointAddress);
}
public static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress)
{
TChannel channel = new DuplexChannelFactory<TChannel>(callbackInstance, binding, endpointAddress).CreateChannel();
ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
return channel;
}
public virtual TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address, Uri via)
{
if (address == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address " );
}
if (( base .CallbackType != null ) && (callbackInstance == null ))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallback1 " )));
}
if (callbackInstance == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallback " )));
}
if (callbackInstance.UserObject == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelNoCallbackUserObject " )));
}
if (! base .HasDuplexOperations())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannel1 " , new object [] { base .Endpoint.Contract.Name })));
}
Type c = callbackInstance.UserObject.GetType();
Type callbackContractType = base .Endpoint.Contract.CallbackContractType;
if ((callbackContractType != null ) && !callbackContractType.IsAssignableFrom(c))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateDuplexChannelBadCallbackUserObject " , new object [] { callbackContractType })));
}
base .EnsureOpened();
TChannel local = (TChannel) base .ServiceChannelFactory.CreateChannel( typeof (TChannel), address, via);
IDuplexContextChannel channel = local as IDuplexContextChannel;
if (channel != null )
{
channel.CallbackInstance = callbackInstance;
}
return local;
}
public static TChannel CreateChannel( object callbackObject, Binding binding, EndpointAddress endpointAddress, Uri via)
{
return DuplexChannelFactory<TChannel>.CreateChannel(DuplexChannelFactory<TChannel>.GetInstanceContextForObject(callbackObject), binding, endpointAddress, via);
}
public static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress, Uri via)
{
TChannel channel = new DuplexChannelFactory<TChannel>(callbackInstance, binding).CreateChannel(endpointAddress, via);
ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
return channel;
}
}
查看以上代码,我们发现DuplexChannelFactory<TChannel>类的CreateChannel()方法中没有不带参数的,那它通过CreateChannel()方法创建TransparentProxy时,肯定是调用了基类的方法。
接下去分析ChannelFactory<TChannel>的CreateChannel方法。代码如下:
public class ChannelFactory<TChannel> : ChannelFactory, IChannelFactory<TChannel>, IChannelFactory, ICommunicationObject
{
public TChannel CreateChannel()
{
return this .CreateChannel( base .CreateEndpointAddress( base .Endpoint), null );
}
public virtual TChannel CreateChannel(EndpointAddress address, Uri via)
{
TChannel local;
bool traceOpenAndClose = base .TraceOpenAndClose;
try
{
using (ServiceModelActivity activity = (DiagnosticUtility.ShouldUseActivity && base .TraceOpenAndClose) ? ServiceModelActivity.CreateBoundedActivity() : null )
{
if (DiagnosticUtility.ShouldUseActivity)
{
ServiceModelActivity.Start(activity, this .OpenActivityName, this .OpenActivityType);
base .TraceOpenAndClose = false ;
}
if (address == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " address " );
}
if ( base .HasDuplexOperations())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxCreateNonDuplexChannel1 " , new object [] { base .Endpoint.Contract.Name })));
}
base .EnsureOpened();
local = (TChannel) this .ServiceChannelFactory.CreateChannel( typeof (TChannel), address, via);
}
}
finally
{
base .TraceOpenAndClose = traceOpenAndClose;
}
return local;
}
}
注意到这一句:
local = (TChannel) this .ServiceChannelFactory.CreateChannel( typeof (TChannel), address, via);
继续分析ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via)的过程:
internal abstract class ServiceChannelFactory : ChannelFactoryBase
{
public object CreateChannel(Type channelType, EndpointAddress address, Uri via)
{
if (via == null )
{
via = this .ClientRuntime.Via;
if (via == null )
{
via = address.Uri;
}
}
ServiceChannel serviceChannel = this .CreateServiceChannel(address, via);
serviceChannel.Proxy = CreateProxy(channelType, channelType, MessageDirection.Input, serviceChannel);
serviceChannel.ClientRuntime.GetRuntime().InitializeChannel((IClientChannel) serviceChannel.Proxy);
OperationContext current = OperationContext.Current;
if ((current != null ) && (current.InstanceContext != null ))
{
current.InstanceContext.WmiChannels.Add((IChannel) serviceChannel.Proxy);
serviceChannel.WmiInstanceContext = current.InstanceContext;
}
return serviceChannel.Proxy;
}
[SecuritySafeCritical]
internal static object CreateProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel)
{
if (!proxiedType.IsInterface)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " SFxChannelFactoryTypeMustBeInterface " )));
}
ServiceChannelProxy proxy = new ServiceChannelProxy(interfaceType, proxiedType, direction, serviceChannel);
return proxy.GetTransparentProxy();
}
}
CreateChannel方法返回的是serviceChannel.Proxy,而serviceChannel.Proxy又是
proxy.GetTransparentProxy()获取到的TransparentProxy.
3、服务调用过程。
WCF客户端对服务接口的调用最终通过RealProxy对象,也就是ServiceChannelProxy的Invoke方法来完成。
下面来看看Invoke方法。
public override IMessage Invoke(IMessage message)
{
IMessage message3;
try
{
IMethodCallMessage methodCall = message as IMethodCallMessage;
if (methodCall == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ArgumentException(SR.GetString( " SFxExpectedIMethodCallMessage " )));
}
MethodData methodData = this .GetMethodData(methodCall);
switch (methodData.MethodType)
{
case MethodType.Service:
return this .InvokeService(methodCall, methodData.Operation);
case MethodType.BeginService:
return this .InvokeBeginService(methodCall, methodData.Operation);
case MethodType.EndService:
return this .InvokeEndService(methodCall, methodData.Operation);
case MethodType.Channel:
return this .InvokeChannel(methodCall);
case MethodType.Object:
return this .InvokeObject(methodCall);
case MethodType.GetType:
return this .InvokeGetType(methodCall);
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( string .Format(CultureInfo.InvariantCulture, " Invalid proxy method type " , new object [ 0 ])));
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw ;
}
message3 = this .CreateReturnMessage(exception, message as IMethodCallMessage);
}
return message3;
}
3.1、MethodData的Service类型
MethodType.Service为同步调用方式;MethodType.BeginService、MethodType.EndService为异步方式。
首先看看MethodType.Service,它调用了ServiceChannelProxy的InvokeService方法完成。InvokeService方法定义如下:
private IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
{
object [] objArray;
object [] ins = operation.MapSyncInputs(methodCall, out objArray);
object ret = this .serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, objArray);
object [] returnArgs = operation.MapSyncOutputs(methodCall, objArray, ref ret);
return this .CreateReturnMessage(ret, returnArgs, methodCall);
}
可以看出,在 InvokeService中,通过serviceChannel.Call返回调用结果,最有又通过ServerChannelProxy的
CreateReturnMessage方法返回Message。
ProxyOperationRuntime在WCF中也是很重要的对象。它的定义以及构造函数如下:
internal class ProxyOperationRuntime
{
// Fields
private string action;
private MethodInfo beginMethod;
private bool deserializeReply;
internal static readonly object [] EmptyArray = new object [ 0 ];
private ParameterInfo[] endOutParams;
private readonly IClientFaultFormatter faultFormatter;
private readonly IClientMessageFormatter formatter;
private ParameterInfo[] inParams;
private readonly bool isInitiating;
private readonly bool isOneWay;
private readonly bool isTerminating;
private readonly string name;
internal static readonly ParameterInfo[] NoParams = new ParameterInfo[ 0 ];
private ParameterInfo[] outParams;
private readonly IParameterInspector[] parameterInspectors;
private readonly ImmutableClientRuntime parent;
private string replyAction;
private ParameterInfo returnParam;
private bool serializeRequest;
private MethodInfo syncMethod;
// Methods
internal ProxyOperationRuntime(ClientOperation operation, ImmutableClientRuntime parent)
{
if (operation == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " operation " );
}
if (parent == null )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( " parent " );
}
this .parent = parent;
this .formatter = operation.Formatter;
this .isInitiating = operation.IsInitiating;
this .isOneWay = operation.IsOneWay;
this .isTerminating = operation.IsTerminating;
this .name = operation.Name;
this .parameterInspectors = EmptyArray<IParameterInspector>.ToArray(operation.ParameterInspectors);
this .faultFormatter = operation.FaultFormatter;
this .serializeRequest = operation.SerializeRequest;
this .deserializeReply = operation.DeserializeReply;
this .action = operation.Action;
this .replyAction = operation.ReplyAction;
this .beginMethod = operation.BeginMethod;
this .syncMethod = operation.SyncMethod;
if ( this .beginMethod != null )
{
this .inParams = ServiceReflector.GetInputParameters( this .beginMethod, true );
if ( this .syncMethod != null )
{
this .outParams = ServiceReflector.GetOutputParameters( this .syncMethod, false );
}
else
{
this .outParams = NoParams;
}
this .endOutParams = ServiceReflector.GetOutputParameters(operation.EndMethod, true );
this .returnParam = operation.EndMethod.ReturnParameter;
}
else if ( this .syncMethod != null )
{
this .inParams = ServiceReflector.GetInputParameters( this .syncMethod, false );
this .outParams = ServiceReflector.GetOutputParameters( this .syncMethod, false );
this .returnParam = this .syncMethod.ReturnParameter;
}
if (( this .formatter == null ) && ( this .serializeRequest || this .deserializeReply))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString( " ClientRuntimeRequiresFormatter0 " , new object [] { this .name })));
}
}
[SecurityCritical]
internal object [] MapSyncInputs(IMethodCallMessage methodCall, out object [] outs)
{
if ( this .outParams.Length == 0 )
{
outs = EmptyArray;
}
else
{
outs = new object [ this .outParams.Length];
}
if ( this .inParams.Length == 0 )
{
return EmptyArray;
}
return methodCall.InArgs;
}
[SecurityCritical]
internal object [] MapSyncOutputs(IMethodCallMessage methodCall, object [] outs, ref object ret)
{
return this .MapOutputs( this .outParams, methodCall, outs, ref ret);
}
[SecurityCritical]
private object [] MapOutputs(ParameterInfo[] parameters, IMethodCallMessage methodCall, object [] outs, ref object ret)
{
if ((ret == null ) && ( this .returnParam != null ))
{
ret = GetDefaultParameterValue(TypeLoader.GetParameterType( this .returnParam));
}
if (parameters.Length == 0 )
{
return null ;
}
object [] args = methodCall.Args;
for ( int i = 0 ; i < parameters.Length; i++)
{
if (outs[i] == null )
{
args[parameters[i].Position] = GetDefaultParameterValue(TypeLoader.GetParameterType(parameters[i]));
}
else
{
args[parameters[i].Position] = outs[i];
}
}
return args;
}
/
****/
}
IMethodCallMessage的InArgs:获取未标记为 out 参数的参数数组;Args:获取传递给该方法的参数数组(MSDN中的定义)。
那么最核心的ServiceChannel的Call方法又做了什么事情呢。。?让我们看看它的定义:
internal object Call( string action, bool oneway, ProxyOperationRuntime operation, object [] ins, object [] outs)
{
return this .Call(action, oneway, operation, ins, outs, this .operationTimeout);
}
internal object Call( string action, bool oneway, ProxyOperationRuntime operation, object [] ins, object [] outs, TimeSpan timeout)
{
this .ThrowIfDisallowedInitializationUI();
this .ThrowIfIdleAborted(operation);
ProxyRpc rpc = new ProxyRpc( this , operation, action, ins, timeout);
using (rpc.Activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null )
{
if (DiagnosticUtility.ShouldUseActivity)
{
ServiceModelActivity.Start(rpc.Activity, SR.GetString( " ActivityProcessAction " , new object [] { action }), ActivityType.ProcessAction);
}
this .PrepareCall(operation, oneway, ref rpc);
if (! this .explicitlyOpened)
{
this .EnsureDisplayUI();
this .EnsureOpened(rpc.TimeoutHelper.RemainingTime());
}
else
{
this .ThrowIfOpening();
base .ThrowIfDisposedOrNotOpen();
}
try
{
ConcurrencyBehavior.UnlockInstanceBeforeCallout(OperationContext.Current);
if (oneway)
{
this .binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
}
else
{
rpc.Reply = this .binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime());
if (rpc.Reply == null )
{
base .ThrowIfFaulted();
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new CommunicationException(SR.GetString( " SFxServerDidNotReply " )));
}
}
}
finally
{
this .CompletedIOOperation();
CallOnceManager.SignalNextIfNonNull( this .autoOpenManager);
ConcurrencyBehavior.LockInstanceAfterCallout(OperationContext.Current);
}
rpc.OutputParameters = outs;
this .HandleReply(operation, ref rpc);
}
return rpc.ReturnValue;
}
上面代码中有至关重要的一段:
if (oneway)
{
this .binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
}
else
{
rpc.Reply = this .binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime());
}
通过是否单程oneway,来进行Send或者Request。那binder由是什么对象呢。。?
在ServiceChannel中,定义:
private readonly IChannelBinder binder。这点可以从RealProxy对象中可以看出来:
在本例中使用netTcpBinding绑定,所以binder为DuplexChannelBinder。不同的协议类型,
binder就不一样。以wsHttpBinding为例,它的binder为RequestChannelBinder。
DuplexChannelBinder的Send与Request定义如下:
public void Send(Message message, TimeSpan timeout)
{
this .channel.Send(message, timeout);
}
public Message Request(Message message, TimeSpan timeout)
{
SyncDuplexRequest request = null ;
bool flag = false ;
RequestReplyCorrelator.PrepareRequest(message);
lock ( this .ThisLock)
{
if (! this .Pumping)
{
flag = true ;
this .syncPumpEnabled = true ;
}
if (!flag)
{
request = new SyncDuplexRequest( this );
}
this .RequestStarting(message, request);
}
if (flag)
{
TimeoutHelper helper = new TimeoutHelper(timeout);
UniqueId messageId = message.Headers.MessageId;
try
{
this .channel.Send(message, helper.RemainingTime());
if ((DiagnosticUtility.ShouldUseActivity && (ServiceModelActivity.Current != null )) && (ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction))
{
ServiceModelActivity.Current.Suspend();
}
while ( true )
{
Message message2;
do
{
TimeSpan span = helper.RemainingTime();
if (! this .channel.TryReceive(span, out message2))
{
throw TraceUtility.ThrowHelperError( this .GetReceiveTimeoutException(timeout), message);
}
if (message2 == null )
{
this .AbortRequests();
return null ;
}
if (message2.Headers.RelatesTo == messageId)
{
this .ThrowIfInvalidReplyIdentity(message2);
return message2;
}
}
while ( this .HandleRequestAsReply(message2));
if (DiagnosticUtility.ShouldTraceInformation)
{
EndpointDispatcher endpointDispatcher = null ;
if (( this .ChannelHandler != null ) && ( this .ChannelHandler.Channel != null ))
{
endpointDispatcher = this .ChannelHandler.Channel.EndpointDispatcher;
}
TraceUtility.TraceDroppedMessage(message2, endpointDispatcher);
}
message2.Close();
}
}
finally
{
lock ( this .ThisLock)
{
this .RequestCompleting( null );
this .syncPumpEnabled = false ;
if ( this .pending > 0 )
{
this .EnsurePumping();
}
}
}
}
TimeoutHelper helper2 = new TimeoutHelper(timeout);
this .channel.Send(message, helper2.RemainingTime());
this .EnsurePumping();
return request.WaitForReply(helper2.RemainingTime());
}
在Request中,除了调用Channel的Send方法以外,还调用了SyncDuplexRequest的WaitForReply返回消息。
SyncDuplexRequest的WaitForReply定义如下:
internal Message WaitForReply(TimeSpan timeout)
{
try
{
if (!TimeoutHelper.WaitOne( this .wait, timeout))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( this .parent.GetReceiveTimeoutException(timeout));
}
}
finally
{
this .CloseWaitHandle();
}
this .parent.ThrowIfInvalidReplyIdentity( this .reply);
return this .reply;
}
3.2MethodData的Channel类型:
private IMethodReturnMessage InvokeChannel(IMethodCallMessage methodCall)
{
string str = null ;
ActivityType unknown = ActivityType.Unknown;
if (DiagnosticUtility.ShouldUseActivity && ((ServiceModelActivity.Current == null ) || (ServiceModelActivity.Current.ActivityType != ActivityType.Close)))
{
MethodData methodData = this .GetMethodData(methodCall);
if ((methodData.MethodBase.DeclaringType == typeof (ICommunicationObject)) && methodData.MethodBase.Name.Equals( " Close " , StringComparison.Ordinal))
{
str = SR.GetString( " ActivityClose " , new object [] { this .serviceChannel.GetType().FullName });
unknown = ActivityType.Close;
}
}
using (ServiceModelActivity activity = string .IsNullOrEmpty(str) ? null : ServiceModelActivity.CreateBoundedActivity())
{
if (DiagnosticUtility.ShouldUseActivity)
{
ServiceModelActivity.Start(activity, str, unknown);
}
return this .ExecuteMessage( this .serviceChannel, methodCall);
}
}
private IMethodReturnMessage ExecuteMessage( object target, IMethodCallMessage methodCall)
{
MethodBase methodBase = methodCall.MethodBase;
object [] args = methodCall.Args;
object ret = null ;
try
{
ret = methodBase.Invoke(target, args);
}
catch (TargetInvocationException exception)
{
return this .CreateReturnMessage(exception.InnerException, methodCall);
}
return this .CreateReturnMessage(ret, args, args.Length, null , methodCall);
}
对于Channel,直接调用methodBase.Invoke进行调用
3.3、MethodData的Object类型
private IMethodReturnMessage InvokeObject(IMethodCallMessage methodCall)
{
return RemotingServices.ExecuteMessage( this .objectWrapper, methodCall);
}
RemotingServices中ExecuteMessage的定义如下:
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
public static IMethodReturnMessage ExecuteMessage(MarshalByRefObject target, IMethodCallMessage reqMsg)
{
if (target == null )
{
throw new ArgumentNullException( " target " );
}
RealProxy realProxy = GetRealProxy(target);
if ((realProxy is RemotingProxy) && !realProxy.DoContextsMatch())
{
throw new RemotingException(Environment.GetResourceString( " Remoting_Proxy_WrongContext " ));
}
StackBuilderSink sink = new StackBuilderSink(target);
return (IMethodReturnMessage) sink.SyncProcessMessage(reqMsg, 0 , true );
}
StackBuilderSink中SyncProcessMessage的处理过程:
public virtual IMessage SyncProcessMessage(IMessage msg)
{
return this .SyncProcessMessage(msg, 0 , false );
}
internal virtual IMessage SyncProcessMessage(IMessage msg, int methodPtr, bool fExecuteInContext)
{
IMessage message3;
IMessage message = InternalSink.ValidateMessage(msg);
if (message != null )
{
return message;
}
IMethodCallMessage message2 = msg as IMethodCallMessage;
LogicalCallContext threadCallContext = null ;
object obj2 = CallContext.GetLogicalCallContext().GetData( " __xADCall " );
bool flag = false ;
try
{
object server = this ._server;
VerifyIsOkToCallMethod(server, message2);
LogicalCallContext callCtx = null ;
if (message2 != null )
{
callCtx = message2.LogicalCallContext;
}
else
{
callCtx = (LogicalCallContext) msg.Properties[ " __CallContext " ];
}
threadCallContext = CallContext.SetLogicalCallContext(callCtx);
flag = true ;
callCtx.PropagateIncomingHeadersToCallContext(msg);
PreserveThreadPrincipalIfNecessary(callCtx, threadCallContext);
if ( this .IsOKToStackBlt(message2, server) && ((Message) message2).Dispatch(server, fExecuteInContext))
{
message3 = new StackBasedReturnMessage();
((StackBasedReturnMessage) message3).InitFields((Message) message2);
LogicalCallContext context4 = CallContext.GetLogicalCallContext();
context4.PropagateOutgoingHeadersToMessage(message3);
((StackBasedReturnMessage) message3).SetLogicalCallContext(context4);
return message3;
}
MethodBase methodBase = GetMethodBase(message2);
object [] outArgs = null ;
object ret = null ;
RemotingMethodCachedData reflectionCachedData = InternalRemotingServices.GetReflectionCachedData(methodBase);
object [] args = Message.CoerceArgs(message2, reflectionCachedData.Parameters);
ret = this .PrivateProcessMessage(methodBase.MethodHandle, args, server, methodPtr, fExecuteInContext, out outArgs);
this .CopyNonByrefOutArgsFromOriginalArgs(reflectionCachedData, args, ref outArgs);
LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
if (((obj2 != null ) && (( bool ) obj2)) && (logicalCallContext != null ))
{
logicalCallContext.RemovePrincipalIfNotSerializable();
}
message3 = new ReturnMessage(ret, outArgs, (outArgs == null ) ? 0 : outArgs.Length, logicalCallContext, message2);
logicalCallContext.PropagateOutgoingHeadersToMessage(message3);
CallContext.SetLogicalCallContext(threadCallContext);
}
catch (Exception exception)
{
message3 = new ReturnMessage(exception, message2);
((ReturnMessage) message3).SetLogicalCallContext(message2.LogicalCallContext);
if (flag)
{
CallContext.SetLogicalCallContext(threadCallContext);
}
}
return message3;
3.4MethodData的GetType类型
private IMethodReturnMessage InvokeGetType(IMethodCallMessage methodCall)
{
return this .CreateReturnMessage( this .proxiedType, null , 0 , SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
}
private IMethodReturnMessage CreateReturnMessage( object ret, object [] outArgs, int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
{
return new ReturnMessage(ret, outArgs, outArgsCount, callCtx, mcm);
}
它调用了ReturnMessage的如下构造函数:
public ReturnMessage( object ret, object [] outArgs, int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
{
this ._ret = ret;
this ._outArgs = outArgs;
this ._outArgsCount = outArgsCount;
if (callCtx != null )
{
this ._callContext = callCtx;
}
else
{
this ._callContext = CallContext.GetLogicalCallContext();
}
if (mcm != null )
{
this ._URI = mcm.Uri;
this ._methodName = mcm.MethodName;
this ._methodSignature = null ;
this ._typeName = mcm.TypeName;
this ._hasVarArgs = mcm.HasVarArgs;
this ._methodBase = mcm.MethodBase;
}
}
4、总结:
WCF的客户端框架中介绍了很多MS封装的内部对象,整个流程的说明介绍这些对象时根据流程的介绍的需要进行
了一些介绍。下面对这些对象做个总结以认清它们之间的关系。
4.1、WCF客户端流程:
WCF客户端流程如下图:
上图流程说明:
1、由DuplexChannelFactory的父类:ChannelFactory<TChannel>的父类ChannelFactory初始化
Endpoint。
2、ChannelFactory调用ServiceChannelFactroy的BuildChannelFactory,通过初始化的Endpoint创建
ServiceChannelFactroy。(根据契约需要的通道形状,会生成继承自ServiceChannelFactory的
ServiceChannelFactoryOverX,)
3、ServiceChannelFactroy创建ServiceChannelFactroy的过程中,会初始化ClientRuntime对象
4、ServiceChannelFactoryOverX通过CreateInnerChannelBinder创建IChannelBinder对象。
5、ServiceChannelFactoryOverX通过CreateInnerChannelBinder方法创建IChannelBinder对象
6、ServiceChannelFactoryOverX通过CreateChannel创建ServiceChannel,并通过ImmutableClientRuntime初始化Channel。
7、实际代理ServiceChannelProxy 通过ServiceChannel对象,契约接口定义生成RealProxy。
8、通过RealProxy获取TransparentProxy对象
9、TransparentProxy对象调用服务
10、ServiceChannel通过IChannelBinder对象发送消息
4.2、WCF客户端使用到的对象关系
在这两节分析WCF客户端时,介绍了很多内部 对象。通过UML关系图描述一下这些类型之间的关系:
在上图中,以接口为分界线,上半部分生成ServiceChannel;下半部分生成调用服务的代理。
4.3、ServiceChannel生成时序图
最后后通过时序图介绍一下ServiceChannel、IChannelBinder对象生成过程:
备注:本节以及 前一节 中所有流程的说明都是以netTcpBiding作为传输协议来进行的,其他协议也类似。
分类: WCF架构体系
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于深入理解WCF系统体系(之二:WCF客户端如何构建?(下))的详细内容...