Получение родительского члена из выражения - PullRequest
5 голосов
/ 20 марта 2012

У меня есть Expression, который используется для получения списка элементов из моего Model для моего просмотра.То, что я хочу сделать, - это Expression для List, могу ли я вернуться назад на Expression Tree один уровень, чтобы получить родительский узел?

Допустим, это моя модель представления:

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

...

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

У меня есть 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(...);
}

Я вызываю своего помощника следующим образом:

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

Все это прекрасно работает, мой вопрос, могу ли я взять данный Expression, который указывает на List<string> и получить его родительский узел (MyClass) затем скомпилируйте его с моим Model, чтобы получить его значение.Итак, эквивалент этого Expression:

m => m.myClass

Вот что я пробовал:

// 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);

Ответы [ 2 ]

4 голосов
/ 20 марта 2012

Должно работать следующее:

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;

    ...
}

Очевидно, вы должны добавить минимум проверки ошибок в этот код, который я намеренно пропустил здесь для краткости.

1 голос
/ 20 марта 2012

Вы должны использовать то же выражение параметра в своем новом лямбда-выражении:

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