转换表达式的正确方法<func <foo,bool =“”>&gt;到另一个表达式<func <bar,bool =“”>&gt; </func <bar,> </func <foo,>

时间:2014-12-04 19:19:28

标签: c# .net c#-4.0 expression linq-expressions

我有两个表达方式。

我有一个Expression<Func<Foo, bool>>

类型的谓词输入

我想将源表达式转换为Expression<Func<Bar, bool>>

类型

这样做的逻辑是什么? 我一直试图使用Expression.Convert(),但我相信我做错了。

1 个答案:

答案 0 :(得分:3)

要将Expression<Func<Foo, bool>>转换为Expression<Func<Bar, bool>>,您还需要Expression<Func<Bar, Foo>>来处理转化。

你正在做的只是编写表达式。组合表达式比组合函数稍微复杂一些,其中一个人可以简单地调用另一个将结果作为参数传递。这里我们需要用第一个函数的主体替换第二个函数的所有参数实例:

public static Expression<Func<TFirstParam, TResult>>
    Compose<TFirstParam, TIntermediate, TResult>(
    this Expression<Func<TFirstParam, TIntermediate>> first,
    Expression<Func<TIntermediate, TResult>> second)
{
    var param = Expression.Parameter(typeof(TFirstParam), "param");

    var newFirst = first.Body.Replace(first.Parameters[0], param);
    var newSecond = second.Body.Replace(second.Parameters[0], newFirst);

    return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}

这依赖于以下方法将一个表达式的所有实例替换为另一个:

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

现在我们可以执行以下操作:

Expression<Func<Foo, bool>> predicate = GetPrediate();
Expression<Func<Bar, Foo>> selector = GetSelector();
Expression<Func<Bar, bool>> newPredicate = selector.Compose(predicate);