Scenario
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)
to
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);
}
}
EDIT
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
[HttpPost]
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
Elements[0]PropertyName
and I get (depending on my tries)
PropertyName
or (maybe not exact, I try to reproduce this case)
Elements.Item[0].PropertyName
EDIT2
Also tried a different solution, working with ViewData.TemplateInfo.HtmlFieldPrefix, but I then get
Elements.[0].PropertyName
(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.