从表达中获取父成员

Gab*_*abe 5 c# lambda expression asp.net-mvc-3

我有一个Expression用于获取Model我的视图中的项目列表.我想要做的,是给定ExpressionList,我可以去向后向上的Expression Tree获取父节点的一个水平?

让我们说这是我的视图模型:

public class MyModel {
   public MyClass myClass { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

...

public class MyClass {
   public List<string> MyList { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我有一个HtmlHelper接受一个Expression如下渲染列表页面:

public static MvcHtmlString RenderList(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TItem>>> dataExpression)
{   
     var list = dataExpression.Compile()(html.ViewData.Model);

     ...

     return MvcHtmlString.Create(...);
}
Run Code Online (Sandbox Code Playgroud)

我打电话给我的助手如下:

@model MyNamespace.Models.MyModel
@Html.RenderList(m => m.myClass.MyList)
Run Code Online (Sandbox Code Playgroud)

这一切都运行正常,我的问题是,我可以采用Expression指向的指定List<string>并获取它的父节点(MyClass)然后针对我编译它Model以获得它的值.所以相当于Expression:

m => m.myClass
Run Code Online (Sandbox Code Playgroud)

这是我尝试过的:

// 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);
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 4

以下应该有效:

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;

    ...
}
Run Code Online (Sandbox Code Playgroud)

显然,您应该向此代码添加最少的错误检查,为简洁起见,我在此处故意省略了该代码。