static LambdaExpression WrapMethodParams(LambdaExpression functionLambda) { /* We are converting: * [ExcelFunction(...)] * public static string myFunc(string input, int otherInput, params object[] args) * { * ... * } * * into: * [ExcelFunction(...)] * public static string myFunc(string input, int otherInput, object arg3, object arg4, object arg5, object arg6, {...until...}, object arg125) * { * // First we figure where in the list to stop building the param array * int lastArgToAdd = 0; * if (!(arg3 is ExcelMissing)) lastArgToAdd = 3; * if (!(arg4 is ExcelMissing)) lastArgToAdd = 4; * ... * if (!(arg125 is ExcelMissing)) lastArgToAdd = 125; * * // Then add until we get there * List<object> args = new List<object>(); * if (lastArgToAdd >= 3) args.Add(arg3); * if (lastArgToAdd >= 4) args.Add(arg4); * ... * if (lastArgToAdd >= 125) args.Add(arg125); * * Array<object> argsArray = args.ToArray(); * return myFunc(input, otherInput, argsArray); * } * * */ int maxArguments; if (ExcelDnaUtil.ExcelVersion >= 12.0) { maxArguments = 125; // Constrained by 255 char registration string, take off 3 type chars, use up to 2 chars per param (before we start doing object...) (& also return) // CONSIDER: Might improve this if we generate the delegate based on the max length... } else { maxArguments = 29; // Or maybe 30? } var normalParams = functionLambda.Parameters.Take(functionLambda.Parameters.Count() - 1).ToList(); var normalParamCount = normalParams.Count; var paramsParamCount = maxArguments - normalParamCount; var allParamExprs = new List <ParameterExpression>(normalParams); var blockExprs = new List <Expression>(); var blockVars = new List <ParameterExpression>(); // Run through the arguments looking for the position of the last non-ExcelMissing argument var lastArgVarExpr = Expression.Variable(typeof(int)); blockVars.Add(lastArgVarExpr); blockExprs.Add(Expression.Assign(lastArgVarExpr, Expression.Constant(0))); for (int i = normalParamCount + 1; i <= maxArguments; i++) { allParamExprs.Add(Expression.Parameter(typeof(object), "arg" + i)); var lenTestParam = Expression.IfThen(Expression.Not(Expression.TypeIs(allParamExprs[i - 1], typeof(ExcelMissing))), Expression.Assign(lastArgVarExpr, Expression.Constant(i))); blockExprs.Add(lenTestParam); } // We know that last parameter is an array type // Create a new list to hold the values var argsArrayType = functionLambda.Parameters.Last().Type; var argsType = argsArrayType.GetElementType(); var argsListType = typeof(List <>).MakeGenericType(argsType); var argsListVarExpr = Expression.Variable(argsListType); blockVars.Add(argsListVarExpr); var argListAssignExpr = Expression.Assign(argsListVarExpr, Expression.New(argsListType)); blockExprs.Add(argListAssignExpr); // And put the (converted) arguments into the list for (int i = normalParamCount + 1; i <= maxArguments; i++) { var testParam = Expression.IfThen(Expression.GreaterThanOrEqual(lastArgVarExpr, Expression.Constant(i)), Expression.Call(argsListVarExpr, "Add", null, TypeConversion.GetConversion(allParamExprs[i - 1], argsType))); blockExprs.Add(testParam); } var argArrayVarExpr = Expression.Variable(argsArrayType); blockVars.Add(argArrayVarExpr); var argArrayAssignExpr = Expression.Assign(argArrayVarExpr, Expression.Call(argsListVarExpr, "ToArray", null)); blockExprs.Add(argArrayAssignExpr); var innerParams = new List <Expression>(normalParams) { argArrayVarExpr }; var callInner = Expression.Invoke(functionLambda, innerParams); blockExprs.Add(callInner); var blockExpr = Expression.Block(blockVars, blockExprs); // Build the delegate type to return var allParamTypes = normalParams.Select(pi => pi.Type).ToList(); var toAdd = maxArguments - allParamTypes.Count; for (int i = 0; i < toAdd; i++) { allParamTypes.Add(typeof(object)); } allParamTypes.Add(functionLambda.ReturnType); Type delegateType; if (maxArguments == 125) { delegateType = typeof(CustomFunc125 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>) .MakeGenericType(allParamTypes.ToArray()); } else // if (maxArguments == 29) { delegateType = typeof(CustomFunc29 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>) .MakeGenericType(allParamTypes.ToArray()); } return(Expression.Lambda(delegateType, blockExpr, allParamExprs)); }