Getting parent member from expression

I have an Expression that is used to get a list of elements from my Model for my view. What I want to do is given Expression for a List , can I go back one level to the Expression Tree to get the parent node?

Let's say this is my look model:

 public class MyModel { public MyClass myClass { get; set;} } 

...

 public class MyClass { public List<string> MyList { get; set;} } 

I have an HtmlHelper that accepts Expression as follows to display a list on a 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 assistant as follows:

 @model MyNamespace.Models.MyModel @Html.RenderList(m => m.myClass.MyList) 

Everything works fine, my question is: can I take a given Expression that points to a List<string> and get its parent node ( MyClass ), and then compile it with my Model to get its value. So the equivalent of this Expression :

 m => m.myClass 

Here is what I 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); 
+4
source share
2 answers

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 errors to check this code, which I intentionally omitted here for brevity.

+4
source

You should use the same parameter expression in your new lambda expression:

 var lambda = Expression.Lambda<Func<MyModel, dynamic>>(exp, this._dataExpression.Parameters); 
+1
source

Source: https://habr.com/ru/post/1402304/


All Articles