Tim*_*ann 2 .net c# reflection expression
我有一个类型的表达式Expression<Func<TElement, TElement, bool>>和一个类型的常量TElement。我需要一个类型的表达式Expression<Func<TElement, bool>>,其中一个参数被常量替换。换句话说,我需要以下方法的主体:
public static Expression<Func<TElement, bool>> ReplaceParameter<TElement>
(
Expression<Func<TElement, TElement, bool>> inputExpression,
TElement element
)
{
...
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话ReplaceParameter((i1, i2) => i1 > i2, 5),我预计结果是i => i > 5。
我在想,它也许能够递归地解构然后重建输入表达式,并用常量表达式替换所有出现的第二个参数。由于有很多不同的表达方式,我不确定如何做到这一点。
ExpressionVisitor是你的朋友:
static void Main()
{
Expression<Func<int, int, bool>> before = (x, y) => x * 2 == y + 1;
var after = ReplaceParameter(before, 3);
Console.WriteLine(after);
}
public static Expression<Func<TElement, bool>> ReplaceParameter<TElement>
(
Expression<Func<TElement, TElement, bool>> inputExpression,
TElement element
)
{
var replacer = new Replacer(inputExpression.Parameters[0],
Expression.Constant(element, typeof(TElement)));
var body = replacer.Visit(inputExpression.Body);
return Expression.Lambda<Func<TElement, bool>>(body,
inputExpression.Parameters[1]);
}
class Replacer : ExpressionVisitor
{
private readonly Expression _from, _to;
public Replacer(Expression from, Expression to)
{
_from = from;
_to = to;
}
public override Expression Visit(Expression node)
=> node == _from ? _to : base.Visit(node);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不会自动折叠纯常量表达式,即显示的代码会导致:
y => ((3 * 2) == (y + 1))
Run Code Online (Sandbox Code Playgroud)
但是,如果您愿意,您可以尝试查找BinaryExpression仅作为ConstantExpression输入的节点,并再次在 内部直接评估节点Replacer。