【问题标题】:How to construct the lambda expression when implementing HiddenForEach with MVC5用 MVC5 实现 HiddenForEach 时如何构造 lambda 表达式
【发布时间】:2016-10-13 15:53:34
【问题描述】:

我正在尝试为 ASP.NET MVC5 实现一个类似于 Html.HiddenFor 的 HTML-Helper 方法,但我想传递一个 IList<T> 并让它为每个人调用 Html.HiddenFor

这是我目前得到的:

public static void HiddenForEach<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IList<TProperty>>> expression)
{
    IList<TProperty> allItems = expression.Compile().Invoke(htmlHelper.ViewData.Model);
    for (int i = 0; i < allItems.Count; ++i)
    {
        var withIndex = Expression.Lambda<Func<TModel, TProperty>>(...??...);
        htmlHelper.ViewContext.Writer.Write(htmlHelper.HiddenFor<TModel, TProperty>(withIndex).ToHtmlString());
    }
}

我正在调用表达式来获取 IList,然后,我正在遍历其中的所有项目。

但是,我不知道如何构建表达式来访问IList 中的一个特定元素,即如何构建表达式以获得与Html.HiddenFor(m =&gt; m.ListOfSomething[0])Html.HiddenFor(m =&gt; m.ListOfSomething[1]) 等价的东西。

此外,我不确定是否应该使用 htmlHelper.ViewContext.Writer 来输出生成的 HTML 或者以某种方式连接 MvcHtmlStrings 并返回它们?

【问题讨论】:

标签: c# asp.net-mvc razor lambda asp.net-mvc-5


【解决方案1】:

这是根据 Matt Griffiths 的建议开发的可行解决方案:

public static MvcHtmlString HiddenForEach<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IList<TProperty>>> expression)
{
    var sb = new StringBuilder();
    IList<TProperty> allItems = expression.Compile().Invoke(htmlHelper.ViewData.Model);
    for (int i = 0; i < allItems.Count; ++i)
    {
        var getListItemExpr = Expression.Call(
            expression.Body, 
            typeof(IList<TProperty>).GetMethod("get_Item"), 
            Expression.Constant(i)
        );

        var lambdaWithIndex = Expression.Lambda<Func<TModel, TProperty>>( 
            getListItemExpr,  
            expression.Parameters
        );

        sb.Append(htmlHelper.HiddenFor(lambdaWithIndex).ToHtmlString());
    }
    return MvcHtmlString.Create(sb.ToString())
}

【讨论】:

    【解决方案2】:

    我将首先声明我不会完全回答你的问题,但我取得的进展可能会帮助其他人解决它。

    本质上,我试图在调用htmlHelper.HiddenFor(); 之前将表达式从x =&gt; x.People 转换为x =&gt; x.People[0]

    for (int i = 0; i < allItems.Count; ++i)
    {
      PropertyInfo indexProperty = typeof(IList<TProperty>).GetProperty("Item");
    
      IndexExpression indexExpression = Expression.MakeIndex(
        expression.Body, 
        indexProperty, 
        new Expression[] { Expression.Constant(i) }
      );
    
      Expression<Func<TModel, TProperty>> lambda = 
        Expression.Lambda<Func<TModel, TProperty>>(
          indexExpression,
          expression.Parameters[0]
      );
    
      MvcHtmlString hidden = htmlHelper.HiddenFor(lambda);
    }
    

    总而言之,我非常接近。唯一的问题是表达式被转换为x =&gt; x.People.Items[0] 并且调用htmlHelper.HiddenFor(lambda) 会导致我无法解决的错误。

    模板只能用于字段访问、属性访问、 一维数组索引,或单参数自定义索引器 表达式

    我会再调查一下,看看我能想出什么。

    【讨论】:

    • 诀窍是不使用索引表达式,而是使用 "get_Item" 方法并使用它来创建 lambda 表达式。我将在单独的答案中发布解决方案,但接受您的解决方案,因为您为我指明了正确的方向。
    • @j00hi 啊,有道理,很好找。
    猜你喜欢
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2015-03-08
    • 2013-05-24
    相关资源
    最近更新 更多