2012-07-05 62 views
3

这里执行现有的表达式是一个简单的类LINQ表达式来对孩子财产

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到实体因此调用Expression.Invoke是行不通的。

+0

通过执行现有的表达你的意思为过滤器像'parents.whereChild(express)'? – 2012-07-05 18:52:42

+0

基本上说'objectIdExpr = obj => obj.ID',我需要一个实体做'p => objectIdExpr.Invoke(p.Child)' – Connell 2012-07-05 18:55:42

+0

检查我的答案,@ SPFiredrake是正确的,我的答案是一样的想法烤成一个很好的lib – Guillaume86 2012-07-06 17:41:03

回答

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

给一个尝试,让我们知道。

+0

这不会工作在linq2entity – 2012-07-05 20:39:35

+0

这是一个很好的解决方案,但改变'swap.Visit(parentEX.Body),objectIdExpr.Parameters);' 'swap.Visit(objectIdExpr.Body),parentEX.Parameters);' – 2012-07-06 08:56:46

+0

谢谢@BalazsTihanyi,我在测试项目中做对了,但不在这里。 D'哦! – SPFiredrake 2012-07-06 14:36:56