My Technical Notes

Sunday, 27 December 2015

C#: Concatenating an Action to a Delegate

Let's say we have an `Action` `a` and a `Delegate` `d` which may or may not return a value. We want a new delegate `e` with the same type as `d`, but which will first execute `a`. Here is a method which will do exactly that:


private static Expression ExpressionInvoke(Delegate _delegate, params Expression[] arguments)
{
    var invokeMethod = _delegate.GetType().GetMethod("Invoke");

    return Expression.Call(Expression.Constant(_delegate), invokeMethod, arguments);
}

public static Delegate ConcatActionToDelegate(Action a, Delegate d)
{
    var parameters =
        d.GetType().GetMethod("Invoke").GetParameters()
        .Select(p => Expression.Parameter(p.ParameterType, p.Name))
        .ToArray();

    Expression body = Expression.Block(ExpressionInvoke(a), ExpressionInvoke(d, parameters));

    var lambda = Expression.Lambda(d.GetType(), body, parameters);

    var compiled = lambda.Compile();
            
    return compiled;
}

No comments: