迭代lambda表达式的属性

Ror*_*san 8 .net c# lambda expression-trees

我试图对一个复杂的控件进行泛化,这个控件经常在我的网站中使用但是具有不同的字段.控件中的功能始终相同,它只是更改的基础字段.

为了实现显示不同字段的方法,我试图创建一个HTMLHelper扩展,它接受Expression<Func<TModel,TProperty>>一个参数,它将包含在控件中显示所需的类的属性.例如:

风景:

@model Project.Core.Page
@Html.MyHelper(p => new { p.Author.Name, p.Author.Location, p.Author.Age });
Run Code Online (Sandbox Code Playgroud)

这是延长我有问题-我该如何遍历提供PARAMS在lambda提供每一个TextBoxFor(),甚至可以手动创建一个input元素,并与填充它valuename拉姆达参数的?

psuedo中的扩展:

public static MvcHtmlString MyHelper<TModel,TProperty>(
    this HtmlHelper<TModel> helper, 
    Expression<Func<TModel,TProperty>> expression) {
    foreach (var parameter in expression.???) {
        // helper.TextBoxFor(???) 
        // TagBuilder("input").Attributes("name", expression.???)
    }
}
Run Code Online (Sandbox Code Playgroud)

我觉得我已经长时间盯着这个了,而且我也觉得有一个更简单的方法,我忽略了实现这个目标.

任何帮助是极大的赞赏.如果您需要更多详细信息,或者我错过了一些重要信息,请告诉我们.

mcl*_*129 2

如果您假设以下情况:

  1. 输入表达式的结果是一个投影(返回一个新对象,匿名或其他)
  2. 投影的元素都是MemberExpressions,并且不包含对模型或其子项上的方法的调用

然后你可以通过使用以下方法来实现你想要的:

编辑:

在意识到我的第一个示例无法处理具有复杂属性的对象后,我更新了代码以使用辅助方法来访问属性值。此方法使用递归遍历属性链以返回适当的值。

public static MvcHtmlString MyHelper<TModel,object>(
    this HtmlHelper<TModel> helper, 
    Expression<Func<TModel,object>> expression) {

        var newExpression = expression.Body as NewExpression;
        TModel model = helper.ViewData.Model;

        foreach (MemberExpression a in newExpression.Arguments) {

            var propertyName = a.Member.Name;
            var propertyValue = GetPropertyValue<TModel>(model, a);

            // Do whatever you need to with the property name and value;

        }

    }

    private static object GetPropertyValue<T>(T instance, MemberExpression me) {

        object target;

        if (me.Expression.NodeType == ExpressionType.Parameter) {
            // If the current MemberExpression is at the root object, set that as the target.            
            target = instance;
        }
        else {                
            target = GetPropertyValue<T>(instance, me.Expression as MemberExpression);
        }

        // Return the value from current MemberExpression against the current target
        return target.GetType().GetProperty(me.Member.Name).GetValue(target, null);

    }
Run Code Online (Sandbox Code Playgroud)

注意:我没有在 IDE 中直接将其实现为 MVC 扩展方法,因此可能需要对语法进行细微的更改。