前一节 介绍了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作为传输协议来进行的,其他协议也类似。