Alter Lambda Expression to go one level deeper

2019-09-09 06:22发布

Suppose I have a method like this:

public void MultiDropDown<T>(Expression<Func<T, DropDownModel<DropDownItem>>> expression)
{

   // Here i want to get more specific with the expression selector
   // Suppose it was passed like this: 
   //                                  MultiDropDown(x => x.MyDropDown);
   // I need to alter `expression` and go deeper:    x => x.MyDropDown.Title;
   // And then use the new expression for other stuff...
}

Solution

Thanks to svick !

public void MultiDropDown<T>(Expression<Func<T, DropDownModel<DropDownItem>>> expression)
{
        // 1. Build a new expression and select the final property
        Expression<Func<DropDownModel<DefaultDropDownItem>, object>> childExpression = x => x.Title;
        // 2. Extract property name
        var propName = (childExpression.Body as MemberExpression).Member.Name;
        // 3. Create a MemberExpression selection from parent's Body
        var expressionProperty = Expression.Property(expression.Body, propName);
        // 4. Finally create a Lambda Expression
        var refinedExpression = Expression.Lambda<Func<TModel, object>>(expressionProperty, expression.Parameters);
}

Operations 1. and 2. were done just for avoiding "Title" string and relying on Strongly Typed model instead.

1条回答
闹够了就滚
2楼-- · 2019-09-09 06:57

What you need is to create an expression that takes the Body of your query and accesses the given property on it. Then you need to build back the lambda expression. The whole thing looks like this:

var titleExpression = Expression.Lambda<Func<T, string>>(
    Expression.Property(expression.Body, "Title"), expression.Parameters);
查看更多
登录 后发表回答