| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Collections.ObjectModel;
- using System.Reflection;
- using System.Runtime;
- using System.Runtime.Remoting.Messaging;
- using System.Security;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Diagnostics.Application;
- class ProxyOperationRuntime
- {
- static internal readonly ParameterInfo[] NoParams = new ParameterInfo[0];
- static internal readonly object[] EmptyArray = new object[0];
- readonly IClientMessageFormatter formatter;
- readonly bool isInitiating;
- readonly bool isOneWay;
- readonly bool isTerminating;
- readonly bool isSessionOpenNotificationEnabled;
- readonly string name;
- readonly IParameterInspector[] parameterInspectors;
- readonly IClientFaultFormatter faultFormatter;
- readonly ImmutableClientRuntime parent;
- bool serializeRequest;
- bool deserializeReply;
- string action;
- string replyAction;
- MethodInfo beginMethod;
- MethodInfo syncMethod;
- MethodInfo taskMethod;
- ParameterInfo[] inParams;
- ParameterInfo[] outParams;
- ParameterInfo[] endOutParams;
- ParameterInfo returnParam;
- 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.isSessionOpenNotificationEnabled = operation.IsSessionOpenNotificationEnabled;
- 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;
- this.taskMethod = operation.TaskMethod;
- this.TaskTResult = operation.TaskTResult;
- 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 && (serializeRequest || deserializeReply))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientRuntimeRequiresFormatter0, this.name)));
- }
- }
- internal string Action
- {
- get { return this.action; }
- }
- internal IClientFaultFormatter FaultFormatter
- {
- get { return this.faultFormatter; }
- }
- internal bool IsInitiating
- {
- get { return this.isInitiating; }
- }
- internal bool IsOneWay
- {
- get { return this.isOneWay; }
- }
- internal bool IsTerminating
- {
- get { return this.isTerminating; }
- }
- internal bool IsSessionOpenNotificationEnabled
- {
- get { return this.isSessionOpenNotificationEnabled; }
- }
- internal string Name
- {
- get { return this.name; }
- }
- internal ImmutableClientRuntime Parent
- {
- get { return this.parent; }
- }
- internal string ReplyAction
- {
- get { return this.replyAction; }
- }
- internal bool DeserializeReply
- {
- get { return this.deserializeReply; }
- }
- internal bool SerializeRequest
- {
- get { return this.serializeRequest; }
- }
- internal Type TaskTResult
- {
- get;
- set;
- }
- internal void AfterReply(ref ProxyRpc rpc)
- {
- if (!this.isOneWay)
- {
- Message reply = rpc.Reply;
- if (this.deserializeReply)
- {
- if (TD.ClientFormatterDeserializeReplyStartIsEnabled())
- {
- TD.ClientFormatterDeserializeReplyStart(rpc.EventTraceActivity);
- }
- rpc.ReturnValue = this.formatter.DeserializeReply(reply, rpc.OutputParameters);
- if (TD.ClientFormatterDeserializeReplyStopIsEnabled())
- {
- TD.ClientFormatterDeserializeReplyStop(rpc.EventTraceActivity);
- }
- }
- else
- {
- rpc.ReturnValue = reply;
- }
- int offset = this.parent.ParameterInspectorCorrelationOffset;
- try
- {
- for (int i = parameterInspectors.Length - 1; i >= 0; i--)
- {
- this.parameterInspectors[i].AfterCall(this.name,
- rpc.OutputParameters,
- rpc.ReturnValue,
- rpc.Correlation[offset + i]);
- if (TD.ClientParameterInspectorAfterCallInvokedIsEnabled())
- {
- TD.ClientParameterInspectorAfterCallInvoked(rpc.EventTraceActivity, this.parameterInspectors[i].GetType().FullName);
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (ErrorBehavior.ShouldRethrowClientSideExceptionAsIs(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- if (parent.ValidateMustUnderstand)
- {
- Collection<MessageHeaderInfo> headersNotUnderstood = reply.Headers.GetHeadersNotUnderstood();
- if (headersNotUnderstood != null && headersNotUnderstood.Count > 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.SFxHeaderNotUnderstood, headersNotUnderstood[0].Name, headersNotUnderstood[0].Namespace)));
- }
- }
- }
- }
- internal void BeforeRequest(ref ProxyRpc rpc)
- {
- int offset = this.parent.ParameterInspectorCorrelationOffset;
- try
- {
- for (int i = 0; i < parameterInspectors.Length; i++)
- {
- rpc.Correlation[offset + i] = this.parameterInspectors[i].BeforeCall(this.name, rpc.InputParameters);
- if (TD.ClientParameterInspectorBeforeCallInvokedIsEnabled())
- {
- TD.ClientParameterInspectorBeforeCallInvoked(rpc.EventTraceActivity, this.parameterInspectors[i].GetType().FullName);
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (ErrorBehavior.ShouldRethrowClientSideExceptionAsIs(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- if (this.serializeRequest)
- {
- if (TD.ClientFormatterSerializeRequestStartIsEnabled())
- {
- TD.ClientFormatterSerializeRequestStart(rpc.EventTraceActivity);
- }
- rpc.Request = this.formatter.SerializeRequest(rpc.MessageVersion, rpc.InputParameters);
- if (TD.ClientFormatterSerializeRequestStopIsEnabled())
- {
- TD.ClientFormatterSerializeRequestStop(rpc.EventTraceActivity);
- }
- }
- else
- {
- if (rpc.InputParameters[0] == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxProxyRuntimeMessageCannotBeNull, this.name)));
- }
- rpc.Request = (Message)rpc.InputParameters[0];
- if (!IsValidAction(rpc.Request, Action))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidRequestAction, this.Name, rpc.Request.Headers.Action ?? "{NULL}", this.Action)));
- }
- }
- internal static object GetDefaultParameterValue(Type parameterType)
- {
- return (parameterType.IsValueType && parameterType != typeof(void)) ? Activator.CreateInstance(parameterType) : null;
- }
- [SecurityCritical]
- internal bool IsSyncCall(IMethodCallMessage methodCall)
- {
- if (this.syncMethod == null)
- {
- return false;
- }
- return (methodCall.MethodBase.MethodHandle == this.syncMethod.MethodHandle);
- }
- [SecurityCritical]
- internal bool IsBeginCall(IMethodCallMessage methodCall)
- {
- if (this.beginMethod == null)
- {
- return false;
- }
- return (methodCall.MethodBase.MethodHandle == this.beginMethod.MethodHandle);
- }
- [SecurityCritical]
- internal bool IsTaskCall(IMethodCallMessage methodCall)
- {
- if (this.taskMethod == null)
- {
- return false;
- }
- return (methodCall.MethodBase.MethodHandle == this.taskMethod.MethodHandle);
- }
- [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[] MapAsyncBeginInputs(IMethodCallMessage methodCall, out AsyncCallback callback, out object asyncState)
- {
- object[] ins;
- if (this.inParams.Length == 0)
- {
- ins = EmptyArray;
- }
- else
- {
- ins = new object[this.inParams.Length];
- }
- object[] args = methodCall.Args;
- for (int i = 0; i < ins.Length; i++)
- {
- ins[i] = args[this.inParams[i].Position];
- }
- callback = args[methodCall.ArgCount - 2] as AsyncCallback;
- asyncState = args[methodCall.ArgCount - 1];
- return ins;
- }
- [SecurityCritical]
- internal void MapAsyncEndInputs(IMethodCallMessage methodCall, out IAsyncResult result, out object[] outs)
- {
- outs = new object[this.endOutParams.Length];
- result = methodCall.Args[methodCall.ArgCount - 1] as IAsyncResult;
- }
- [SecurityCritical]
- internal object[] MapSyncOutputs(IMethodCallMessage methodCall, object[] outs, ref object ret)
- {
- return MapOutputs(this.outParams, methodCall, outs, ref ret);
- }
- [SecurityCritical]
- internal object[] MapAsyncOutputs(IMethodCallMessage methodCall, object[] outs, ref object ret)
- {
- return MapOutputs(this.endOutParams, methodCall, outs, ref ret);
- }
- [SecurityCritical]
- 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)
- {
- // the RealProxy infrastructure requires a default value for value types
- args[parameters[i].Position] = GetDefaultParameterValue(TypeLoader.GetParameterType(parameters[i]));
- }
- else
- {
- args[parameters[i].Position] = outs[i];
- }
- }
- return args;
- }
- static internal bool IsValidAction(Message message, string action)
- {
- if (message == null)
- {
- return false;
- }
- if (message.IsFault)
- {
- return true;
- }
- if (action == MessageHeaders.WildcardAction)
- {
- return true;
- }
- return (String.CompareOrdinal(message.Headers.Action, action) == 0);
- }
- }
- }
|