减少LambdaExpression签名
本文关键字:签名 LambdaExpression 减少 | 更新日期: 2023-09-27 18:27:37
我想不出更好的方法来表达这个问题,但我想做的是在计算LambdaExpression之前,通过处理FilterObject
的实例,将LambdaExpression的签名从Expression<Func<MyObject, FilterObject, bool>>
减少到Expression<Func<MyObject, bool>>
。
这里有一个快速的例子:
AddFilter("Filter Name", FilterTypes.All,
(x, y) => GetConjunctionResult(
x.PersonA.IsSomething, x.PersonB.IsSomething, y.ConjunctionType));
private static bool GetConjunctionResult(bool personA, bool personB,
ConjunctionType conjunctionType)
{
switch (conjunctionType)
{
case ConjunctionType.Both:
return personA && personB:
case ConjunctionType.Either:
return personA && personB;
case ConjunctionType.PersonA:
return personA;
case ConjunctionType.PersonB:
return personB;
case ConjunctionType.Neither:
return !personA && !personB;
}
}
因此,我希望AddFilter
的重载创建一个FilterObject
类型的对象,并将其嵌入到LambdaExpression中,如下所示:
var filter = new FilterObject();
// create Expression<Func<MyObject, bool>> lambda = x => GetConjunctionResult(
// x.PersonA.IsSomething, x.PersonB.IsSomething, filter.ConjunctionType));
现在可能有更好的方法来做到这一点,所以我愿意接受任何完全避开这种方法的建议。
给定
var filter = new FilterObject()
应该是:
Expression<Func<MyObject, bool>> exp2 =
Expression.Lambda<Func<MyObject, bool>>(
Expression.Invoke(myExp,
myExp.Parameters[0],
Expression.Constant(filter)),
myExp.Parameters[0]);
Expression.Invoke
将调用另一个表达式,并将新表达式的第一个参数作为第一个参数传递,并将带有过滤器的Expression.Constant
作为第二个参数传递。
您是否尝试将Currying与Expression树结合使用?
比调用Invoke
更好的方法是直接使用ExpressionVisitor
替换表达式树中的参数。您可以定义几个简单的扩展方法来简化这一过程。在这种情况下,他们可以应用表达式的第一个参数(您需要更改签名或调整签名以应用中间参数)。
用法:
var applied = expr.Apply(constValueForFirstParameter);
在静态类中定义以下扩展方法:
public static Expression<Func<U, V, bool>> Apply<T, U, V>(this Expression<Func<T, U, V, bool>> input, T value)
{
var swap = new ExpressionSubstitute(input.Parameters[0], Expression.Constant(value));
var lambda = Expression.Lambda<Func<U, V, bool>>(swap.Visit(input.Body), input.Parameters[1], input.Parameters[2]);
return lambda;
}
public static Expression<Func<U, bool>> Apply<T, U>(this Expression<Func<T, U, bool>> input, T value)
{
var swap = new ExpressionSubstitute(input.Parameters[0], Expression.Constant(value));
var lambda = Expression.Lambda<Func<U, bool>>(swap.Visit(input.Body), input.Parameters[1]);
return lambda;
}
class ExpressionSubstitute : System.Linq.Expressions.ExpressionVisitor
{
private readonly Expression from, to;
public ExpressionSubstitute(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
if (node == from) return to;
return base.Visit(node);
}
}