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);
interworking VP come it’s not such an issue, and rumor has it that it’s that C# 4 will also solve the issue having to write code such as:
Run(“…”, Type.Missing, Type.Missing, …);
But for everyone else, you can solve the problem with an extension method and dynamic lambda expressions.
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 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)


