我有一个类型的表达式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
)
{
...
}
如果我打电话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);
}
请注意,这不会自动折叠纯常量表达式,即显示的代码会导致:
y => ((3 * 2) == (y + 1))
You could但是,如果您愿意,请尝试寻找BinaryExpression
那个只有ConstantExpression
作为输入,并再次在内部直接评估节点Replacer
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)