views:

172

answers:

2

I have the following:

Expression<Func<Car, int>> myExpr = car => car.Wheel.Tyre.Pressure;

I want to remove the parameter, and make the first member the parameter for a sub-expression, so i end up with:

Expression<Func<Wheel, int>> mySubExpr = wheel => wheel.Tyre.Pressure;

This needs to work for any expression tree of the above format, including MemberExpression, MethodCallExpression and any other Expression which has a .Expression property. For example:

Expression<Func<Car, int>> myOtherExpr = car => car.GetRearLeftWheel().GetTyre().Pressure

or

Expression<Func<Car, int>> anotherExpr = car => car.Wheel.GetTyre().GetPressure();

How would I achieve this elegantly?

Thanks

Andrew

+1  A: 

Did you check out Metalinq and its EditableExpression?

zvolkov
no i havent, but if thats even half decent ive got a million uses for it and it'll be freaking awesome. nice one
Andrew Bullock
+1  A: 

Start with the class from this page Then sprinkle in this code and I think you have a solution (the test stuff was how I tested it, I think it is pretty much the same as what you did):

class Test
{
 public Test()
 {
  Expression<Func<string, string>> trim2 = s => s.Substring(1).Substring(1);
  var modifier = new PopModifier();
  Expression<Func<string, string>> trim1 = (Expression<Func<string, string>>)modifier.Modify(trim2);

  var test2 = trim2.Compile();
  var test1 = trim1.Compile();
  var input = "abc";
  if (test2(input) != "c")
  {
   throw new Exception();
  }
  if (test1(input) != "bc")
  {
   throw new Exception();
  }   
 }
}

public class PopModifier : ExpressionVisitor
{
 bool didModify = false;

 public Expression Modify(Expression expression)
 {
  return Visit(expression);
 }

 protected override Expression VisitMethodCall(MethodCallExpression m)
 {
  if (!didModify)
  {
   didModify = true;
   return m.Object;
  }

  return base.VisitMethodCall(m);
 }
}
Jake Pearson
thanks, i shall try it shortly
Andrew Bullock