| File: FrameworkFork\System.ServiceModel\System\ServiceModel\Dispatcher\SyncMethodInvoker.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Reflection; using System.Runtime; using System.Runtime.Diagnostics; using System.ServiceModel.Diagnostics; using System.Threading.Tasks; namespace System.ServiceModel.Dispatcher { public class SyncMethodInvoker : IOperationInvoker { private readonly MethodInfo _method; private InvokeDelegate _invokeDelegate; private int _inputParameterCount; private int _outputParameterCount; private string _methodName; public SyncMethodInvoker(MethodInfo method) { if (method == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("method")); } _method = method; } public MethodInfo Method { get { return _method; } } public string MethodName { get { if (_methodName == null) _methodName = _method.Name; return _methodName; } } public object[] AllocateInputs() { EnsureIsInitialized(); return EmptyArray<object>.Allocate(_inputParameterCount); } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { return InvokeAsync(instance, inputs).ToApm(callback, state); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { var task = result as Task<Tuple<object, object[]>>; if (task == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRServiceModel.SFxInvalidCallbackIAsyncResult)); } var tuple = task.Result; outputs = tuple.Item2; return tuple.Item1; } private Task<Tuple<object, object[]>> InvokeAsync(object instance, object[] inputs) { EnsureIsInitialized(); if (instance == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRServiceModel.SFxNoServiceObject)); if (inputs == null) { if (_inputParameterCount > 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRServiceModel.SFxInputParametersToServiceNull, _inputParameterCount))); } else if (inputs.Length != _inputParameterCount) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRServiceModel.SFxInputParametersToServiceInvalid, _inputParameterCount, inputs.Length))); var outputs = EmptyArray<object>.Allocate(_outputParameterCount); long beginOperation = 0; bool callSucceeded = false; bool callFaulted = false; EventTraceActivity eventTraceActivity = null; if (WcfEventSource.Instance.OperationCompletedIsEnabled() || WcfEventSource.Instance.OperationFaultedIsEnabled() || WcfEventSource.Instance.OperationFailedIsEnabled()) { beginOperation = DateTime.UtcNow.Ticks; OperationContext context = OperationContext.Current; if (context != null && context.IncomingMessage != null) { eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(context.IncomingMessage); } } object returnValue; try { ServiceModelActivity activity = null; IDisposable boundActivity = null; if (DiagnosticUtility.ShouldUseActivity) { activity = ServiceModelActivity.CreateBoundedActivity(true); boundActivity = activity; } else if (TraceUtility.MessageFlowTracingOnly) { Guid activityId = TraceUtility.GetReceivedActivityId(OperationContext.Current); if (activityId != Guid.Empty) { DiagnosticTraceBase.ActivityId = activityId; } } else if (TraceUtility.ShouldPropagateActivity) { //Message flow tracing only scenarios use a light-weight ActivityID management logic Guid activityId = ActivityIdHeader.ExtractActivityId(OperationContext.Current.IncomingMessage); if (activityId != Guid.Empty) { boundActivity = Activity.CreateActivity(activityId); } } using (boundActivity) { if (DiagnosticUtility.ShouldUseActivity) { ServiceModelActivity.Start(activity, string.Format(SRServiceModel.ActivityExecuteMethod, _method.DeclaringType.FullName, _method.Name), ActivityType.ExecuteUserCode); } if (WcfEventSource.Instance.OperationInvokedIsEnabled()) { WcfEventSource.Instance.OperationInvoked(eventTraceActivity, MethodName, TraceUtility.GetCallerInfo(OperationContext.Current)); } returnValue = _invokeDelegate(instance, inputs, outputs); callSucceeded = true; } } catch (System.ServiceModel.FaultException) { callFaulted = true; throw; } finally { if (beginOperation != 0) { if (callSucceeded) { if (WcfEventSource.Instance.OperationCompletedIsEnabled()) { WcfEventSource.Instance.OperationCompleted(eventTraceActivity, _methodName, TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); } } else if (callFaulted) { if (WcfEventSource.Instance.OperationFaultedIsEnabled()) { WcfEventSource.Instance.OperationFaulted(eventTraceActivity, _methodName, TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); } } else { if (WcfEventSource.Instance.OperationFailedIsEnabled()) { WcfEventSource.Instance.OperationFailed(eventTraceActivity, _methodName, TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); } } } } return Task.FromResult(Tuple.Create(returnValue, outputs)); } private void EnsureIsInitialized() { if (_invokeDelegate == null) { EnsureIsInitializedCore(); } } private void EnsureIsInitializedCore() { // Only pass locals byref because InvokerUtil may store temporary results in the byref. // If two threads both reference this.count, temporary results may interact. int inputParameterCount; int outputParameterCount; var invokeDelegate = new InvokerUtil().GenerateInvokeDelegate(Method, out inputParameterCount, out outputParameterCount); _outputParameterCount = outputParameterCount; _inputParameterCount = inputParameterCount; _invokeDelegate = invokeDelegate; // must set this last due to race } } }