Adding var args support to office integration functions with dynamic lambda expressions
Anyone who’s ever done office integration has come across a method definition like so:
object Run(object Macro, object Arg1, object Arg2, …, object Arg30);
if you're working in VB it’s not such an issue, and rumor has it that it’s that C# 4 will also solve the problem of code such as:
Run(“…”, Type.Missing, Type.Missing,/*28 more times*/ …, Type.Missing);
But for everyone else, you can avoid the extra typing with an extension method and dynamic lambda expressions. For example with:
public static class OfficeHelpers { private static MemberInfo missingMemberInfo = typeof(Type).GetMembers().Where(mi => mi.Name == "Missing").Single(); private static MethodInfo runMethodInfo = typeof(_Application).GetMethod("Run"); private static ParameterExpression macroNameParamExp = Expression.Parameter(typeof(string), "macroName"); private static ParameterExpression argsParamExp = Expression.Parameter(typeof(object[]), "args"); public static object Run(this Application App, string macroName, params object[] args) { var argsExprs = GenerateArgs(runMethodInfo, macroName, args); var callExpr = Expression.Call(Expression.Constant(App), runMethodInfo, argsExprs); var paramExprs = new ParameterExpression[] { macroNameParamExp, argsParamExp }; var lambda = Expression.Lambda>(callExpr, paramExprs); return lambda.Compile().Invoke(macroName, args); } private static IEnumerable<Expression> GenerateArgs(MethodInfo runfuncMI, string macroName, object[] args) { yield return macroNameParamExp; for (int ii = 0; ii < args.Length; ii++) yield return BinaryExpression.ArrayIndex(argsParamExp, Expression.Constant(ii, typeof(int))); for (int ii = 0; ii < runfuncMI.GetParameters().Length - args.Length - 1; ii++) yield return Expression.MakeMemberAccess(null, missingMemberInfo); }
a call to
OfficeHelpers.Run("…", arg1,arg2,arg3);
will generate and execute an expression like so:
(macroName, args) => RunFuncTest(macroName, args[0], args[1], args[2], Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing)