public static object CallMethod(string methodName, bool staticMethod, Type typeToCall, object callee, IEnumerable<object> args, Type[] typeArgs, Engine engine) { var bindingFlags = (staticMethod ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; var methodInfo = null as MethodInfo; if (typeArgs != null) { // Use type arguments to choose overload. methodInfo = typeToCall.GetMethod(methodName, bindingFlags, null, typeArgs, null); } else { // Look for a matching method. var candidates = typeToCall.GetMethods(bindingFlags).Where(info => info.Name == methodName); var count = candidates.Count(); if (count >= 1) { if (count == 1) methodInfo = candidates.First(); else { // Use arguments to choose overload. var types = args.Select(value => value != null ? value.GetType() : typeof(object)); methodInfo = typeToCall.GetMethod(methodName, bindingFlags, null, types.ToArray(), null); if (methodInfo == null) engine.Throw("method overload not found: " + methodName); } } } if (methodInfo == null) engine.Throw("method not found: " + methodName); var parameters = methodInfo.GetParameters(); var methodArgs = null as object[]; if (HasParamsParameter(parameters)) { var m = parameters.Length - 1; var initiaArgs = ConvertArguments(parameters.Take(m), args.Take(m)); var paramsType = parameters[m].ParameterType.GetElementType(); var remainingArgs = TypeHelper.CreateArray(args.Skip(m).ToArray(), paramsType); methodArgs = initiaArgs.Concat(new object[] { remainingArgs }).ToArray(); } else { if (parameters.Length != args.Count()) engine.Throw("argument count mismatch: {0} != {1}", parameters.Length, args.Count()); methodArgs = ConvertArguments(parameters, args).ToArray(); } bool trace = engine.ShouldTrace(TraceFlags.Call); if (trace) { TraceCall("args", methodName, args, engine); TraceCall("methodArgs", methodName, methodArgs, engine); } var result = methodInfo.Invoke(callee, methodArgs); if (trace) engine.Trace(TraceFlags.Call, "Call {0} = {1}", methodName, result); return result; }