Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams This question makes no sense at all, how should a method that expexts an entity be replaced by one that doesn´t? I can´t see any reason to rely on the outer scope to get rid of the methods parameter. Sounds like you´re actulally trying to solve something different. So what´s your actual question? MakePeaceGreatAgain Nov 23, 2016 at 11:35 @HimBromBeere I assume he wants to "curry" the function - in this sample, by using a closure. Luaan Nov 23, 2016 at 11:42

That's what Expression.Invoke is for.

Create a new lambda expression, and use Expression.Invoke on the original expression to compose the two expressions.

Sample:

Expression<Func<string, int>> inner = x => int.Parse(x);
var outer = Expression.Lambda<Func<int>>
              (Expression.Invoke(inner, Expression.Constant("123")));
outer.Compile()().Dump(); // 123

Sadly, some expression parsers don't handle Invoke correctly - they assume it to be an invocation of a method, and reject it. In that case, you need to inline the expression. That means visiting the whole inner expression and replacing the ParameterExpressions with variables in the better case, or if parser doesn't support that either, inlining the argument in all the places.

  • Invoke the expression as Luaan suggested
  • Replace the parameters with the value you would like (a constant or a different expression)
  • Option 1 is as simple as Expression.Invoke but may not be compatible with libraries such as LINQ. Option 2 is best done using an expression visitor:

        private class ExchangeParametersVisitor : ExpressionVisitor
            public ParameterExpression Parameter { get; set; }
            public Expression Value { get; set; }
            protected override Expression VisitParameter(ParameterExpression node)
                if (node == Parameter)
                    return Value;
                return node;
    

    What you need to do is apply the visitor to the body of your lambda expression and use it to create a new lambda expression that contains all parameters as before except the one you replaced.

    A nice example of replacing the parameters :) Though I have to note that you need to make sure Value has no side-effects - otherwise replacing the parameter expression will cause trouble. Using a variable would be better, but I'm afraid that the same systems that reject Invoke will also not support variables :) – Luaan Nov 23, 2016 at 11:43 @Luaan Yes. Since variables are afaik not supported by the C#-compiler for a use in expressions, I think it is even more unlikely for an expression parser to accept variables than invokes of an expression. – Georg Nov 23, 2016 at 11:50 The C# compiler doesn't support block-like expressions at all, sadly, which includes variables. And most people don't think of languages like F# when designing their libraries. To be fair, it's not always easy to translate things like this - but e.g. EF does support let, which can be used in a similar way. E.g. Expression<Func<string, int>> inner = x => (from a in x let b = a - '0' select b).Sum();, which translates to two "nested" Selects. – Luaan Nov 23, 2016 at 11:59

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.