Linq Expression用于在子属性上执行现有表达式

时间:2012-07-05 18:33:52

标签: c# linq linq-to-entities expression-trees

这是一个简单的类

public class Parent
{
    public Child Child { get; set; }
}

以下是我正在尝试实施的方法

Expression<Func<Parent, long>> GetChildIDExpr(Expression<Func<Child, long>> objectIdExpr)
{
    //So I need to return an expression that can accept a Parent
    //and apply the given expression to its Child property.
}

听起来很简单,但我无法解决这个问题!

如何实施此方法?

修改

我正在使用LINQ to Entities,因此调用Expression.Invoke无法正常工作。

2 个答案:

答案 0 :(得分:1)

最终,您似乎想要组合表达式。这是问题所在:表达式树是不可变的,它们将保持它们的参数引用,这使得很难将它们链接在一起。但是,这并不是说它无法完成(或者不太难)。但是,您需要ExpressionVisitor的帮助,它将交换父参数和子参数。

class SwapVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public SwapVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
         return node == from ? to : base.Visit(node);
    }
}

然后您可以在GetChildIDExpr

中将它们链接在一起
Expression<Func<Parent, long>> GetChildIDExpr(Expression<Func<Child, long>> objectIdExpr)
{
    Expression<Func<Parent, Child>> parentEX = p => p.Child;
    var swap = new SwapVisitor(objectIdExpr.Parameters[0], parentEX.Body);
    var newExpr = Expression.Lambda<Func<Parent, long>>(
           swap.Visit(objectIdExpr.Body), parentEX.Parameters);
    return newExpr;
}

尝试一下,让我们知道。

答案 1 :(得分:1)

您可以使用LinqKit http://www.albahari.com/nutshell/linqkit.aspx 使用AsExpandable()Compile() / Invoke(),它将内联外部表达式,允许在Linq-to-sql或Linq-to-entities中使用