I have an Expression
that is used to get a list of items from my Model
for my View.
What I want to do, is given the Expression
for the List
, can I go backwards upward on the Expression Tree
one level to get the parent node?
Let's say this is my view model:
public class MyModel {
public MyClass myClass { get; set;}
}
...
public class MyClass {
public List<string> MyList { get; set;}
}
I have an HtmlHelper
that takes an Expression
as follows to render a list to the page:
public static MvcHtmlString RenderList(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TItem>>> dataExpression)
{
var list = dataExpression.Compile()(html.ViewData.Model);
...
return MvcHtmlString.Create(...);
}
I call my helper as follows:
@model MyNamespace.Models.MyModel
@Html.RenderList(m => m.myClass.MyList)
This all works fine, my question is, can I take the given Expression
which points to the List<string>
and get it's parent node (MyClass
) then compile it against my Model
to get it's value. So the equivalent of this Expression
:
m => m.myClass
Here's what I have tried:
// This gets the correct expression
var exp = ((MemberExpression)this._dataExpression.Body).Expression;
// Create a parameter representing the type of the Model ?
var parameter = Expression.Parameter(typeof(TModel));
// Create lambda
var lambda = Expression.Lambda<Func<TModel, dynamic>>(exp, parameter);
// Try and compile against the view model
var obj = lambda.Compile()(html.ViewData.Model);
The following should work:
public static IHtmlString RenderList<TModel, TItem>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, IEnumerable<TItem>>> dataExpression
)
{
var parentEx = ((MemberExpression)dataExpression.Body).Expression;
var lambda = Expression.Lambda<Func<TModel, object>>(parentEx, dataExpression.Parameters[0]);
var value = ModelMetadata.FromLambdaExpression(lambda, html.ViewData).Model;
...
}
Obviously you should add a minimum of error checking to this code which I have intentionally omitted here for brevity.
You have to use the same parameter expression in your new lambda expression:
var lambda = Expression.Lambda<Func<MyModel, dynamic>>(exp,
this._dataExpression.Parameters);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With