private object CallMethod()

in SimpleJsonRpc/SimpleRpcServer.cs [232:283]


        private object CallMethod(string rpcMethodName, object[] methodArgs)
        {
            // locate the method
            if (!rpcMethods.ContainsKey(rpcMethodName))
            {
                throw new ArgumentException($"Rpc method name: {rpcMethodName} not found in registered functions.");
            }

            MethodInfo method = rpcMethods[rpcMethodName].meth;
            var callableObject = rpcMethods[rpcMethodName].obj;

            // determine if the last item is a parameter array
            // see https://stackoverflow.com/questions/627656/determining-if-a-parameter-uses-params-using-reflection-in-c
            // and https://stackoverflow.com/questions/6484651/calling-a-function-using-reflection-that-has-a-params-parameter-methodbase
            var paramArray = method.GetParameters();
            if (paramArray.Length > 0 && paramArray.Last().IsDefined(typeof(ParamArrayAttribute), false))
            {
                // we need the object array to have a sub-array with anything after the number of normal parameters.
                // copy all the normal parameters into an object array
                object[] normalargs = new object[paramArray.Length];
                Array.Copy(methodArgs, normalargs, paramArray.Length - 1);

                // copy all the extra args into a seperate array
                Array extraArgs = Array.CreateInstance(paramArray.Last().ParameterType.GetElementType(), methodArgs.Length - (paramArray.Length - 1));
                Array.Copy(methodArgs, paramArray.Length - 1, extraArgs, 0, extraArgs.Length);

                // set the last item of the paramArray to to the extraArgs array
                normalargs[normalargs.Length - 1] = extraArgs;

                // rebind methodArgs
                methodArgs = normalargs;
            }

            // handle default args - add type missing for all arguments that are optional.
            // if we're handling parameter arrays, this isn't an issue since then every other arg was populated.
            if (paramArray.Length > methodArgs.Length)
            {
                object[] argsWithDefaults = new object[paramArray.Length];
                Array.Copy(methodArgs, argsWithDefaults, methodArgs.Length);

                for (int i = methodArgs.Length; i < paramArray.Length; i++)
                {
                    argsWithDefaults[i] = Type.Missing;
                }

                // rebind methodargs
                methodArgs = argsWithDefaults;
            }

            object result = method.Invoke(callableObject, methodArgs);
            return result;
        }