expressions:在运行时绑定LambdaExpression输入
本文关键字:LambdaExpression 输入 绑定 运行时 expressions | 更新日期: 2023-09-27 17:51:06
考虑以下设置:
class A { public int x; }
class B { public int y; }
static class Helper
{
public static Expression<Func<B>> BindInput(
Expression<Func<A, B>> expression,
A input)
{
//TODO
}
}
static void Main(string[] args)
{
Expression<Func<B>> e = Helper.BindInput(
(A a) => new B { y = a.x + 3 },
new A { x = 4 });
Func<B> f = e.Compile();
Debug.Assert(f().y == 7);
}
我想在方法BindInput
中做的是将表达式转换为将input
嵌入其中。在Main
的示例用法中,结果表达式e
将是
() => new B { y = input.x + 3 }
其中input
是传递给BindInput
的第二个值。
我该怎么做呢?
编辑:我应该补充说,下面的表达式e
是不是我正在寻找的:
((A a) => new B { y = a.x + 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<Func<B>> BindInput(Expression<Func<A, B>> expression, A input)
{
var parameter = expression.Parameters.Single();
var visitor = new MyExpressionVisitor(parameter, input);
return Expression.Lambda<Func<B>>(visitor.Visit(expression.Body));
}
}