259 lines
9.1 KiB
C#
259 lines
9.1 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
namespace System.ServiceModel.Dispatcher
|
|
{
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using System.Runtime;
|
|
using System.Security;
|
|
using System.ServiceModel.Channels;
|
|
using System.ServiceModel.Description;
|
|
using System.ServiceModel.Diagnostics;
|
|
using System.Workflow.Runtime;
|
|
|
|
class WorkflowOperationInvoker : IOperationInvoker
|
|
{
|
|
static object[] emptyObjectArray = new object[0];
|
|
bool canCreateInstance;
|
|
DispatchRuntime dispatchRuntime;
|
|
int inParameterCount;
|
|
bool isOneWay;
|
|
OperationDescription operationDescription;
|
|
ServiceAuthorizationManager serviceAuthorizationManager;
|
|
string staticQueueName;
|
|
MethodInfo syncMethod;
|
|
WorkflowInstanceLifetimeManagerExtension workflowInstanceLifeTimeManager;
|
|
WorkflowRuntime workflowRuntime;
|
|
|
|
public WorkflowOperationInvoker(OperationDescription operationDescription, WorkflowOperationBehavior workflowOperationBehavior,
|
|
WorkflowRuntime workflowRuntime, DispatchRuntime dispatchRuntime)
|
|
{
|
|
if (operationDescription == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationDescription");
|
|
}
|
|
|
|
if (workflowRuntime == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowRuntime");
|
|
}
|
|
|
|
if (workflowOperationBehavior == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowOperationBehavior");
|
|
}
|
|
|
|
this.isOneWay = operationDescription.IsOneWay;
|
|
|
|
if (operationDescription.BeginMethod != null)
|
|
{
|
|
this.syncMethod = operationDescription.BeginMethod;
|
|
inParameterCount = GetFlowedInParameterCount(operationDescription.BeginMethod.GetParameters()) - 2;
|
|
}
|
|
else
|
|
{
|
|
this.syncMethod = operationDescription.SyncMethod;
|
|
inParameterCount = GetFlowedInParameterCount(operationDescription.SyncMethod.GetParameters());
|
|
}
|
|
|
|
this.operationDescription = operationDescription;
|
|
this.workflowRuntime = workflowRuntime;
|
|
this.canCreateInstance = workflowOperationBehavior.CanCreateInstance;
|
|
this.serviceAuthorizationManager = workflowOperationBehavior.ServiceAuthorizationManager;
|
|
this.dispatchRuntime = dispatchRuntime;
|
|
staticQueueName = QueueNameHelper.Create(this.syncMethod.DeclaringType, operationDescription.Name);
|
|
}
|
|
|
|
public bool CanCreateInstance
|
|
{
|
|
get { return this.canCreateInstance; }
|
|
}
|
|
|
|
public DispatchRuntime DispatchRuntime
|
|
{
|
|
get { return this.dispatchRuntime; }
|
|
}
|
|
|
|
public WorkflowInstanceLifetimeManagerExtension InstanceLifetimeManager
|
|
{
|
|
get
|
|
{
|
|
if (this.workflowInstanceLifeTimeManager == null)
|
|
{
|
|
this.workflowInstanceLifeTimeManager = this.dispatchRuntime.ChannelDispatcher.Host.Extensions.Find<WorkflowInstanceLifetimeManagerExtension>();
|
|
}
|
|
|
|
return this.workflowInstanceLifeTimeManager;
|
|
}
|
|
}
|
|
|
|
public bool IsOneWay
|
|
{
|
|
get { return this.isOneWay; }
|
|
}
|
|
|
|
public bool IsSynchronous
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public string StaticQueueName
|
|
{
|
|
get { return this.staticQueueName; }
|
|
}
|
|
|
|
public object[] AllocateInputs()
|
|
{
|
|
if (inParameterCount == 0)
|
|
{
|
|
return emptyObjectArray;
|
|
}
|
|
return new object[inParameterCount];
|
|
}
|
|
|
|
public object Invoke(object instance, object[] inputs, out object[] outputs)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
|
|
}
|
|
|
|
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
|
|
{
|
|
long beginTime = 0;
|
|
|
|
if (PerformanceCounters.PerformanceCountersEnabled)
|
|
{
|
|
PerformanceCounters.MethodCalled(this.operationDescription.Name);
|
|
|
|
try
|
|
{
|
|
if (UnsafeNativeMethods.QueryPerformanceCounter(out beginTime) == 0)
|
|
{
|
|
beginTime = -1;
|
|
}
|
|
}
|
|
catch (SecurityException exception)
|
|
{
|
|
DiagnosticUtility.TraceHandledException(exception, TraceEventType.Warning);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityException(SR.GetString("PartialTrustPerformanceCountersNotEnabled"), exception));
|
|
}
|
|
}
|
|
|
|
Authorize();
|
|
|
|
WorkflowDurableInstance durableInstance = (WorkflowDurableInstance) instance;
|
|
|
|
Fx.Assert(durableInstance.CurrentOperationInvocation == null,
|
|
"At the time WorkflowOperationInvoker.InvokeBegin is called, the WorkflowDurableInstance.CurrentOperationInvocation is expected to be null given the ConcurrencyMode.Single.");
|
|
|
|
durableInstance.CurrentOperationInvocation = new WorkflowOperationAsyncResult(
|
|
this,
|
|
durableInstance,
|
|
inputs,
|
|
callback,
|
|
state,
|
|
beginTime);
|
|
|
|
return durableInstance.CurrentOperationInvocation;
|
|
}
|
|
|
|
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
|
|
{
|
|
bool methodThrewException = false;
|
|
|
|
if (result == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
|
|
}
|
|
|
|
WorkflowDurableInstance durableInstance = (WorkflowDurableInstance) instance;
|
|
WorkflowOperationAsyncResult asyncResult = (WorkflowOperationAsyncResult) result;
|
|
|
|
Fx.Assert(durableInstance.CurrentOperationInvocation != null,
|
|
"At the time WorkflowOperationInvoker.InvokeEnd is called, the WorkflowDurableInstance.CurrentOperationInvocation is expected to be present.");
|
|
|
|
try
|
|
{
|
|
return WorkflowOperationAsyncResult.End(asyncResult, out outputs);
|
|
}
|
|
catch (FaultException)
|
|
{
|
|
methodThrewException = true;
|
|
if (PerformanceCounters.PerformanceCountersEnabled)
|
|
{
|
|
PerformanceCounters.MethodReturnedFault(this.operationDescription.Name);
|
|
}
|
|
throw;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
methodThrewException = true;
|
|
|
|
if (Fx.IsFatal(e))
|
|
{
|
|
throw;
|
|
}
|
|
|
|
if (PerformanceCounters.PerformanceCountersEnabled)
|
|
{
|
|
PerformanceCounters.MethodReturnedError(this.operationDescription.Name);
|
|
}
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
durableInstance.CurrentOperationInvocation = null;
|
|
|
|
if (!methodThrewException)
|
|
{
|
|
if (PerformanceCounters.PerformanceCountersEnabled)
|
|
{
|
|
long currentTime = 0;
|
|
long duration = 0;
|
|
|
|
if ((asyncResult.BeginTime >= 0) && (UnsafeNativeMethods.QueryPerformanceCounter(out currentTime) != 0))
|
|
{
|
|
duration = currentTime - asyncResult.BeginTime;
|
|
}
|
|
PerformanceCounters.MethodReturnedSuccess(this.operationDescription.Name, duration);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int GetFlowedInParameterCount(System.Reflection.ParameterInfo[] parameterInfos)
|
|
{
|
|
int inputCount = 0;
|
|
|
|
foreach (System.Reflection.ParameterInfo parameterInfo in parameterInfos)
|
|
{
|
|
if (parameterInfo.IsOut)
|
|
{
|
|
if (parameterInfo.IsIn)
|
|
{
|
|
++inputCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++inputCount;
|
|
}
|
|
}
|
|
return inputCount;
|
|
}
|
|
|
|
void Authorize()
|
|
{
|
|
Fx.Assert(OperationContext.Current != null, "Not in service dispatch thread");
|
|
|
|
if (this.serviceAuthorizationManager != null)
|
|
{
|
|
if (!this.serviceAuthorizationManager.CheckAccess(OperationContext.Current))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|