3

Here is a simple class

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

Here is the method I'm trying to implement

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

Sounds simple enough, but I just can't work it out!

How can I implement this method?

EDIT:

I'm using LINQ to Entities so calling Expression.Invoke isn't going to work.

Connell
  • 13,925
  • 11
  • 59
  • 92

2 Answers2

1

Ultimately it seems like you want to combine expressions. Here's the problem though: Expression trees are immutable, and they will maintain their parameter references which makes it hard to chain these together. However, that's not to say it can't be done (or isn't too difficult). You need the help of an ExpressionVisitor however, that will swap the parent and child parameter references.

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

Then you can just chain them together in your 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;
}

Give that a try and let us know.

Community
  • 1
  • 1
SPFiredrake
  • 3,852
  • 18
  • 26
1

You can use LinqKit http://www.albahari.com/nutshell/linqkit.aspx with AsExpandable() and Compile()/Invoke(), it will inline external expressions, allowing use in Linq-to-sql or Linq-to-entities

Guillaume86
  • 14,341
  • 4
  • 53
  • 53