3

我想不出更好的方法来表达这个问题,但我想做的是通过在评估 LambdaExpression 之前处理 LambdaExpression 的实例Expression<Func<MyObject, FilterObject, bool>>来减少 LambdaExpression 的签名。Expression<Func<MyObject, bool>>FilterObject

这是一个简单的例子:

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));

现在可能有更好的方法来做到这一点,所以我愿意接受任何完全避开这种方法的建议。

4

2 回答 2

0

给定

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 与表达式树一起使用?

于 2013-08-14T16:09:15.740 回答
0

比调用更好的方法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);
    }
}
于 2015-11-10T02:55:55.123 回答