如何通过解析razor帮助器中的表达式来获取复杂(嵌套)属性的值?

问题描述 投票:1回答:1

我有一个剃刀助手来渲染树视图下拉列表。我试图制作类似于DropDownFor助手,以便在视图中轻松熟悉地使用。是否有解析通过表达式提供的模型属性的值,而不是DataBinder.Eval()

以前我可以通过使用PropertyInfo.GetValue方法解决问题,但它在检索属性的值时遇到问题,该属性是我使用索引器进行预测的集合:model => model.SettingsModel.Categories[i].CategoryKey

public static ITreeViewDropdown<ITreeViewItem> TreeDropDownFor<TModel, TProperty, ITreeViewItem>(
            this HtmlHelper<TModel> html,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<ITreeViewModel<ITreeViewItem>> tree,
            string optionLabel,
            object htmlAttributes = null)

        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            TModel model = (TModel)html.ViewContext.ViewData.ModelMetadata.Model;

            var memberExpr = expression.Body as MemberExpression;
            if (memberExpr == null)
            {
                throw new ArgumentException($"Expected body of type '{typeof(MemberExpression).Name}' but received '{expression.Body.GetType().Name}'", nameof(expression));
            }

            MemberInfo propertyMember = memberExpr.Member;
            string propertyName = ExpressionHelper.GetExpressionText(expression);

            if (propertyMember.MemberType != MemberTypes.Property)
            {
                throw new MemberAccessException($"{propertyName} must be a property");
            }

            // An alternative is needed here
            var propertyValue = DataBinder.Eval(model, propertyName);

            return new TreeViewDropdown<ITreeViewItem>(html, tree, propertyName, propertyValue, optionLabel, htmlAttributes);
        }

上述解决方案目前适合我的需求:

@Html.TreeViewDropdownFor(m => m.SettingsModel.Categories[i].CategoryKey, Model.CategoryTree, "Please Select")

但我read认为Eval()方法可能很慢,我想以'正确'的方式做到这一点,我想不出如何获得SettingsModel.Categories[i].CategoryKey的价值。如果提供的表达式更简单,例如,我可以轻松获得我需要的值。

m = > m.ProjectViewModel.CategoryKey,但没有收藏和索引器。

c# asp.net-mvc razor
1个回答
0
投票

expression.Compile().Invoke(model)实际上得到了正确的价值。考虑到这些类型是通用的,我认为它不会比这更好

© www.soinside.com 2019 - 2024. All rights reserved.