System.Linq.Expressions:在运行时绑定LambdaExpression输入

请考虑以下设置:

class A { public int x; } class B { public int y; } static class Helper { public static Expression<Func> BindInput( Expression<Func> expression, A input) { //TODO } } static void Main(string[] args) { Expression<Func> e = Helper.BindInput( (A a) => new B { y = ax + 3 }, new A { x = 4 }); Func f = e.Compile(); Debug.Assert(f().y == 7); } 

我想在BindInput方法中BindInput是将表达式转换为嵌入到其中的input 。 在Main的示例用法中,结果表达式e将是

 () => new B { y = input.x + 3 } 

其中input是传递给BindInput的第二个值。

我该怎么做呢?

编辑:

我应该补充说下面的表达式e 不是我想要的:

 ((A a) => new B { y = ax + 3 })(input) 

这将获得相当简单,因为它只涉及在现有表达式之上添加一个层。

经过大量的搜索,我偶然发现了神奇的ExpressionVisitor类。 以下似乎完美地运作:

 class MyExpressionVisitor : ExpressionVisitor { public ParameterExpression TargetParameterExpression { get; private set; } public object TargetParameterValue { get; private set; } public MyExpressionVisitor(ParameterExpression targetParameterExpression, object targetParameterValue) { this.TargetParameterExpression = targetParameterExpression; this.TargetParameterValue = targetParameterValue; } protected override Expression VisitParameter(ParameterExpression node) { if (node == TargetParameterExpression) return Expression.Constant(TargetParameterValue); return base.VisitParameter(node); } } static class Helper { public static Expression> BindInput(Expression> expression, A input) { var parameter = expression.Parameters.Single(); var visitor = new MyExpressionVisitor(parameter, input); return Expression.Lambda>(visitor.Visit(expression.Body)); } }