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;
}