File: FrameworkFork\System.ServiceModel\System\ServiceModel\Dispatcher\InvokerUtil.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.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
 
namespace System.ServiceModel.Dispatcher
{
    internal delegate object InvokeDelegate(object target, object[] inputs, object[] outputs);
 
    internal sealed class InvokerUtil
    {
        private readonly CriticalHelper _helper;
 
        public InvokerUtil()
        {
            _helper = new CriticalHelper();
        }
 
        internal InvokeDelegate GenerateInvokeDelegate(MethodInfo method, out int inputParameterCount,
            out int outputParameterCount)
        {
            return _helper.GenerateInvokeDelegate(method, out inputParameterCount, out outputParameterCount);
        }
 
        private class CriticalHelper
        {
            internal InvokeDelegate GenerateInvokeDelegate(MethodInfo method, out int inputParameterCount, out int outputParameterCount)
            {
                ParameterInfo[] parameters = method.GetParameters();
                bool returnsValue = method.ReturnType != typeof(void);
                var inputCount = parameters.Length;
                inputParameterCount = inputCount;
 
                var outputParamPositions = new List<int>();
                for (int i = 0; i < inputParameterCount; i++)
                {
                    if (parameters[i].ParameterType.IsByRef)
                    {
                        outputParamPositions.Add(i);
                    }
                }
 
                var outputPos = outputParamPositions.ToArray();
                outputParameterCount = outputPos.Length;
 
                InvokeDelegate lambda = delegate (object target, object[] inputs, object[] outputs)
                {
                    object[] inputsLocal = null;
                    if (inputCount > 0)
                    {
                        inputsLocal = new object[inputCount];
                        for (var i = 0; i < inputCount; i++)
                        {
                            inputsLocal[i] = inputs[i];
                        }
                    }
                    object result = null;
                    if (returnsValue)
                    {
                        result = method.Invoke(target, inputsLocal);
                    }
                    else
                    {
                        method.Invoke(target, inputsLocal);
                    }
                    for (var i = 0; i < outputPos.Length; i++)
                    {
                        outputs[i] = inputs[outputPos[i]];
                    }
 
                    return result;
                };
 
                return lambda;
            }
        }
    }
}