Как получить значение сложного (вложенного) свойства с помощью синтаксического анализа выражения в помощнике бритвы? - PullRequest
1 голос
/ 04 апреля 2019

У меня есть вспомогательный инструмент для рендеринга в виде дерева. Я пытаюсь сделать это похоже на помощник 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")

Но я прочитал , что метод Eval () может быть медленным, и я хочу сделать это «правильным» способом, и я не могу придумать, как еще получить значение SettingsModel.Categories[i].CategoryKey , Я могу легко получить нужное мне значение, если приведенное выражение проще, например,

m = > m.ProjectViewModel.CategoryKey, но не с коллекциями и индексатором.

1 Ответ

0 голосов
/ 05 апреля 2019

expression.Compile().Invoke(model) фактически получает правильное значение.Учитывая, что типы являются общими, я не думаю, что это станет лучше, чем этот

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...