void OverflowIntoParams(List<Argument> arguments, ParameterInfo[] parameters) { if (arguments.Count == 0 || parameters.Length == 0) return; var overflowingArgs = arguments.Skip(parameters.Length - 1).ToList(); var lastParam = parameters.Last(); if (overflowingArgs.Count == 1 && overflowingArgs[0].Type == lastParam.ParameterType) return; Expr argExpr; if (lastParam.IsParams()) { var elementType = lastParam.ParameterType.GetElementType(); if (overflowingArgs.Any(arg => arg.Type != elementType && !arg.Type.IsSubclassOf(elementType))) return; argExpr = Expr.NewArrayInit( elementType, overflowingArgs.Select(arg => Expr.Convert(arg.Expression, elementType))); } else if (lastParam.ParameterType == typeof(Varargs)) { argExpr = Expr.New( MemberInfos.NewVarargs, Expr.NewArrayInit( typeof(object), overflowingArgs.Select(arg => Expr.Convert(arg.Expression, typeof(object))))); } else { return; } arguments.RemoveRange(arguments.Count - overflowingArgs.Count, overflowingArgs.Count); arguments.Add(new Argument(argExpr, lastParam.ParameterType)); }
private void EmitMethodWithParameterCombo(int thissIdx, MethodInfo realMethod, Type[] parameters, MethodBuilder methodBuilder, ParameterInfo[] realParams) { var gen = methodBuilder.GetILGenerator(); if (!realMethod.IsStatic) { // Set 'this' to the result of JishProxy.GetInstance. This allows one // class to proxy to methods from different source classes. SetReferenceToAppropriateThis(gen, thissIdx); } for (int i = 0; i < parameters.Length; i++) { if (IsParamsArray(realParams[i])) { break; // Break as this is the last parameter (params must always be last) } // if (IsParamDelegate(realParams[i])) // TODO: This is in the wrong place // { // If the param is a delegate it needs to be replaced with a string which // will be used to find the 'real' delegate in the jish_internal scope. // } // Else add standard inline arg gen.Emit(OpCodes.Ldarg, i + 1); } for (int i = parameters.Count(); i < realParams.Length; i++) { if (IsParamsArray(realParams[i])) break; gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldc_I4, thissIdx); // Load the this index into the stack for GetInstance param gen.Emit(OpCodes.Ldc_I4, i); MethodInfo getLastOptional = typeof (JishProxy).GetMethod("GetOptionalParameterDefaultValue"); getLastOptional = getLastOptional.MakeGenericMethod(new[] {realParams[i].ParameterType}); gen.Emit(OpCodes.Callvirt, getLastOptional); } ParameterInfo last = realParams.Any() ? realParams.Last() : null; if (last != null && IsParamsArray(last)) { CovertRemainingParametersToArray(parameters, gen, realParams.Count() - 1, last.ParameterType.GetElementType()); } // Call the real method gen.Emit(realMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, realMethod); gen.Emit(OpCodes.Ret); }