- Replace parameter in lambda expression
- public class Foo
- {
- public int a { get; set; }
- public int b { get; set; }
- }
- private void Test()
- {
- List<Foo> foos = new List<Foo>();
- foos.Add(new Foo());
- foos.Add(new Foo());
- Expression<Func<Foo, int>> exp0 = f => f.a * f.b;
- Expression<Func<int>> exp1 = () => foos[0].a * foos[0].b;
- Expression<Func<int>> exp2 = () => foos[1].a * foos[1].b;
- }
- Foo foo = new Foo();
- Expression<Func<int>> exp = () => foo.a * foo.a + foo.b;
- string result1 = GetResult(exp); // gets "v_001 * v_001 + v_002"
- List<Foo> foes = new List<Foo>();
- foes.Add(new Foo());
- foes.Add(new Foo());
- Expression<Func<int>> exp2 = () => foes.Sum(f => f.a * f.a + f.b);
- string result2 = GetResult(exp2); // should get "(v_001 * v_001 + v_002) + (v_003 * v_003 + v_004)"
- public static class ParameterReplacer
- {
- // Produces an expression identical to 'expression'
- // except with 'source' parameter replaced with 'target' expression.
- public static Expression<TOutput> Replace<TInput, TOutput>
- (Expression<TInput> expression,
- ParameterExpression source,
- Expression target)
- {
- return new ParameterReplacerVisitor<TOutput>(source, target)
- .VisitAndConvert(expression);
- }
- private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor
- {
- private ParameterExpression _source;
- private Expression _target;
- public ParameterReplacerVisitor
- (ParameterExpression source, Expression target)
- {
- _source = source;
- _target = target;
- }
- internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root)
- {
- return (Expression<TOutput>)VisitLambda(root);
- }
- protected override Expression VisitLambda<T>(Expression<T> node)
- {
- // Leave all parameters alone except the one we want to replace.
- var parameters = node.Parameters
- .Where(p => p != _source);
- return Expression.Lambda<TOutput>(Visit(node.Body), parameters);
- }
- protected override Expression VisitParameter(ParameterExpression node)
- {
- // Replace the source with the target, visit other params as usual.
- return node == _source ? _target : base.VisitParameter(node);
- }
- }
- }
- var zeroIndexIndexer = Expression.MakeIndex
- (Expression.Constant(foos),
- typeof(List<Foo>).GetProperty("Item"),
- new[] { Expression.Constant(0) });
- // .ToString() of the below looks like the following:
- // () => (value(System.Collections.Generic.List`1[App.Foo]).Item[0].a
- // * value(System.Collections.Generic.List`1[App.Foo]).Item[0].b)
- var exp1Clone = ParameterReplacer.Replace<Func<Foo, int>, Func<int>>
- (exp0, exp0.Parameters.Single(), zeroIndexIndexer);