Building an indexed expression from another expression c# expression-trees lambda



public class Element {
   public int Id {get;set;}

public class ViewModel {
   public IList<Element> Elements{get;set;}

I have a method with a parameter of type Expression<Func<Element, int>>, which looks like m => m.Id

I'd like to transform

m => m.Id (where m is an Element)


x => x.Elements[0].Id where x is a ViewModel, and 0 is an "index" parameter

What I have now (It's of course generic, I removed the generic part for clarity)

public static class Helpers {
    public static Expression<Func<ViewModel, int>> BuildExpressionArrayFromExpression(
                this Expression<Func<Element, int>> expression,
                ViewModel model,
                int index = 0, 
                string bindingPropertyName = "Elements"//the name of the "List" property in ViewModel class
       var parameter = Expression.Parameter(typeof(ViewModel), "x");
       var viewModelProperty = model.GetType().GetProperty(bindingPropertyName);
       Expression member = parameter;//x => x
       member = Expression.Property(member, viewModelProperty);//x => x.Elements

       var test1 =  Expression.Property(member, "Item", new Expression[]{Expression.Constant(index)});
       //x => x.Elements.Item[0], and I don't want Item

       var test2 = Expression.Call(member, viewModelProperty.PropertyType.GetMethod("get_Item"), new Expression[] {Expression.Constant(index)});
       //x 0> x.Elements.get_Item(0), and I don't want get_Item(0)

       //code to add Id property to expression, not problematic
       return Expression.Lambda<Func<ViewModel, int>(member, parameter);


I need x => x.Elements[0] and not x => x.Elements.Item[0], because the resulting expression must be called with an InputExtensions.TextBoxFor(<myIndexedExpression>)

Imagine a class like that

public class Test {
  public int Id {get;set;}
  public IList<Element> Elements {get;set;}

and a Post Action

public ActionResult Edit(Test model) {
 bla bla bla.

If the name attributes of my inputs are not well generated, I then have binding problems (model.Elements is empty in my Post Action).

Name attribute of my input should be


and I get (depending on my tries)


or (maybe not exact, I try to reproduce this case)



Also tried a different solution, working with ViewData.TemplateInfo.HtmlFieldPrefix, but I then get


(and Elements_0_PropertyName as Id).

The first dot is unwanted in name, and the first "double underscore" should be a simple one in id.

I actually use this solution, working with regex (argh) to remove the unwanteds . and _ , but I'd like to avoid this.

4/25/2013 10:31:32 AM

Accepted Answer

This is just a matter of the string representation of the expression tree, and you don't get to change that. The expression tree you're building is fine. You can see the same effect if you use a lambda expression to build the expression tree:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

class Test
    public static void Main()
        Expression<Func<List<string>, string>> expression = list => list[0];


list => list.get_Item(0)

I'd be very surprised if the result of calling ToString() on the expression tree was really the problem you're facing. Instead of telling us the result you think you need and the vague "I need it for MVC binding reasons" justification, you should explain what's actually going wrong. I strongly suspect the problem isn't where you think it is.

4/24/2013 5:34:26 PM

Popular Answer

Expression<Func<Element, int>> expr1 =
    m => m.Id;
Expression<Func<ViewModel, Element>> expr2 =
    x => x.Elements[0];

Expression<Func<ViewModel, int>> result =


expr1 = m => m.Id
expr2 = x => x.Elements.get_Item(0)
result = x => x.Elements.get_Item(0).Id

It replaces the parameter of expr1 (m) with the body of expr2 (x.Elements[0]), and replaces the input parameter with that from expr2 (x).

Extension method ComposeWith:

public static class FunctionalExtensions
    public static Expression<Func<TInput,TResult>> ComposeWith<TInput,TParam,TResult>(
        this Expression<Func<TParam,TResult>> left, Expression<Func<TInput,TParam>> right)
        var param = left.Parameters.Single();

        var visitor = new ParameterReplacementVisitor(p => {
            if (p == param)
                return right.Body;
            return null;

        return Expression.Lambda<Func<TInput,TResult>>(

    private class ParameterReplacementVisitor : ExpressionVisitor
        private Func<ParameterExpression, Expression> _replacer;

        public ParameterReplacementVisitor(Func<ParameterExpression, Expression> replacer)
            _replacer = replacer;

        protected override Expression VisitParameter(ParameterExpression node)
            var replaced = _replacer(node);
            return replaced ?? node;

Related Questions

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow