如何合并没有调用两个C#Lambda表达式? [英] How to merge two C# Lambda Expressions without an invoke?

查看:195
本文介绍了如何合并没有调用两个C#Lambda表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想合并下列表达式:

// example class
class Order
{
    List<OrderLine> Lines       
}
class OrderLine { }

Expression<Func<Order, List<OrderLine>>> selectOrderLines = o => o.Lines;
Expression<Func<List<OrderLine>, Boolean>> validateOrderLines = lines => lines.Count > 0;

// now combine those to
Expression<Func<Order, Boolean>> validateOrder;



我把它用在selectOrderLines一个调用,并将结果提供给validateOrderLines工作,但由于我使用实体框架中这些表情,我要真正创建一个干净的表达式,应该代表:

I got it to work using a invoke on the selectOrderLines and supplying the result to the validateOrderLines, but because I'm using these expressions in Entity Framework, I have to actually create a clean expression which should represent:

Expression<Func<Order, Boolean>> validateOrder = o => o.Lines.Count > 0;



我怎样才能做到这一点?

How can I do this?

推荐答案

最优雅的方式是使用表达访问者。特别是,该 MSDN博客条目介绍如何使用它,而不调用到谓词(使用布尔And或Or)相结合。

The most elegant way is to use an Expression Visitor. In particular, this MSDN Blog Entry describes how to use it to combine predicates (using boolean And or Or) without Invoke.

EDITED 在意识到布尔组合是不是你想要的,我写ExpressionVisitor的样本使用可以解决您的特定问题:

EDITED Having realized boolean combination is not what you wanted, I wrote a sample usage of ExpressionVisitor that solves for your particular problem:

public class ParameterToMemberExpressionRebinder : ExpressionVisitor
{
    ParameterExpression _paramExpr;
    MemberExpression _memberExpr;

    ParameterToMemberExpressionRebinder(ParameterExpression paramExpr, MemberExpression memberExpr) 
    {
        _paramExpr = paramExpr;
        _memberExpr = memberExpr;
    }

    protected override Expression Visit(Expression p)
    {
        return base.Visit(p == _paramExpr ? _memberExpr : p);
    }

    public static Expression<Func<T, bool>> CombinePropertySelectorWithPredicate<T, T2>(
        Expression<Func<T, T2>> propertySelector,
        Expression<Func<T2, bool>> propertyPredicate)
    {
        var memberExpression = propertySelector.Body as MemberExpression;

        if (memberExpression == null)
        {
            throw new ArgumentException("propertySelector");
        }

        var expr = Expression.Lambda<Func<T, bool>>(propertyPredicate.Body, propertySelector.Parameters);
        var rebinder = new ParameterToMemberExpressionRebinder(propertyPredicate.Parameters[0], memberExpression);
        expr = (Expression<Func<T, bool>>)rebinder.Visit(expr);

        return expr;
    }

    class OrderLine
    {
    }

    class Order
    {
        public List<OrderLine> Lines;
    }

    static void test()
    {
        Expression<Func<Order, List<OrderLine>>> selectOrderLines = o => o.Lines;
        Expression<Func<List<OrderLine>, Boolean>> validateOrderLines = lines => lines.Count > 0;
        var validateOrder = ParameterToMemberExpressionRebinder.CombinePropertySelectorWithPredicate(selectOrderLines, validateOrderLines);

        // validateOrder: {o => (o.Lines.Count > 0)}
    }
}

这篇关于如何合并没有调用两个C#Lambda表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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