如何从现有LambdaExpression建立LambdaExpression不编译 [英] How to build a LambdaExpression from an existing LambdaExpression Without Compiling

查看:145
本文介绍了如何从现有LambdaExpression建立LambdaExpression不编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想两个LambdaExpressions不编译它们结合起来。

I want to combine two LambdaExpressions without compiling them.

这是什么样子,如果我做它们编译:

This is what it looks like if I do compile them:

    public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
        Expression<Func<TContainer,TMember>> getMemberExpression, 
        Expression<Func<TMember,bool>> memberPredicateExpression)
    {
        return x => memberPredicateExpression.Compile()(getMemberExpression.Compile()(x));
    }

这显然不是来从提供的参数目标表达式的最快方法。此外,它使得与查询提供类似的LINQ to不支持C#的方法调用SQL不兼容。

That's obviously not the fastest way to get the target expression from the provided arguments. Also, it makes it incompatible with query providers like LINQ to SQL that do not support C# method calls.

从我读过它看起来像最好的办法是建立一个 ExpressionVisitor 类。然而,这似乎是它可能是一个很常见的任务。有谁知道一个现有的开源代码为基础提供这种功能呢?如果没有,什么是接近 ExpressionVisitor ,使其尽可能地通用的最好方法?

From what I've read it seems like the best approach is to build an ExpressionVisitor class. However, this seems like it could be a pretty common task. Does anyone know of an existing open source code base that provides this kind of functionality? If not, what is the best way to approach the ExpressionVisitor to make it as generic as possible?

推荐答案

我不知道这是否是最好的方式,但你可以做这样的事情:

I don't know if it's the best way, but you could do something like that:

public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
    Expression<Func<TContainer,TMember>> getMemberExpression, 
    Expression<Func<TMember,bool>> memberPredicateExpression)
{
    ParameterExpression x = Expression.Parameter(typeof(TContainer), "x");
    return Expression.Lambda<Func<TContainer, bool>>(
        Expression.Invoke(
            memberPredicateExpression,
            Expression.Invoke(
                getMemberExpression,
                x)),
        x);
}



用法:

Usage:

var expr = CreatePredicate(
    (Foo f) => f.Bar,
    bar => bar % 2 == 0);



结果:

Result:

x => Invoke(bar => ((bar % 2) == 0), Invoke(f => f.Bar, x))

我想这将是更好地得到类似 X => x.Bar%2 == 0 ,但它很可能是显著更难...

I guess it would be better to get something like x => x.Bar % 2 == 0, but it would probably be significantly harder...

编辑:实际上它是不是很难与表达访问者:

actually it wasn't so hard with an expression visitor:

public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
    Expression<Func<TContainer,TMember>> getMemberExpression, 
    Expression<Func<TMember,bool>> memberPredicateExpression)
{
    return CombineExpressionVisitor.Combine(
        getMemberExpression,
        memberPredicateExpression);
}

class CombineExpressionVisitor : ExpressionVisitor
{
    private readonly ParameterExpression _parameterToReplace;
    private readonly Expression _replacementExpression;
    private CombineExpressionVisitor(ParameterExpression parameterToReplace, Expression replacementExpression)
    {
        _parameterToReplace = parameterToReplace;
        _replacementExpression = replacementExpression;
    }

    public static Expression<Func<TSource, TResult>> Combine<TSource, TMember, TResult>(
        Expression<Func<TSource, TMember>> memberSelector,
        Expression<Func<TMember, TResult>> resultSelector)
    {
         var visitor = new CombineExpressionVisitor(
            resultSelector.Parameters[0],
            memberSelector.Body);
        return Expression.Lambda<Func<TSource, TResult>>(
            visitor.Visit(resultSelector.Body),
            memberSelector.Parameters);
    }

    protected override Expression VisitParameter(ParameterExpression parameter)
    {
        if (parameter == _parameterToReplace)
            return _replacementExpression;
        return base.VisitParameter(parameter);
    }
}



这给出了以下表达式:

It gives the following expression:

f => ((f.Bar % 2) == 0)

这篇关于如何从现有LambdaExpression建立LambdaExpression不编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆