【问题标题】:Are lambda expressions supported by Razor?Razor 是否支持 lambda 表达式?
【发布时间】:2011-06-23 03:21:59
【问题描述】:

Razor 视图引擎是否支持 lambda 表达式/匿名方法?

我在 Razor 中难以表达以下内容:

@Model.ToList().ForEach(i =>
    {
        if (i.DealerName != null) 
        {
            <text> 
                @i.DealerName
            </text>
        }
    }

注意:我知道可以用 @foreach 解决这个问题,但我需要一个类似的解决方案来处理第 3 方 MVC 控件。它使用这种机制来设置控件的内容。它适用于 MVC .ASPX 视图,但无法使其与 Razor 一起使用。


MVC .ASPX 等效项(我想转换为 Razor 语法的代码):

<% Model.ToList().ForEach(i =>
       {
           if (i.DealerName != null)
           { 
           %> <%=i.DealerName%> <%
           };
       }); 
%>

这适用于 ASP.NET MVC3 附带的 Razor 引擎。

【问题讨论】:

    标签: asp.net-mvc lambda razor


    【解决方案1】:

    您可以使用Response.Write(i.DealerName); 代替&lt;text&gt;@i.DealerName&lt;/text&gt;

    结果是一样的,就像你把它放到 Razor 页面中一样 - 它会在渲染页面时执行。坦率地说 - 我很确定无论如何它都会被编译成这样。

    此外,由于ForEach() 返回 void,您必须将其作为代码块放到页面中。 所以你的代码看起来像这样:

    @{
        Model.ToList().ForEach(i =>
        {
            if (i.DealerName != null) 
            {
                Response.Write(i.DealerName);
            }
        });
    }
    

    UPD:如果您有更严格的格式,您可以使用这个不错的小技巧:
    (不幸的是,这里的代码着色不会给这个 sn-p 任何功劳,但如果你把它放到 Visual Studio 中,你肯定会明白我的意思。注意:这仅适用于 Razor 页面,而不适用于代码文件 :))

    @{
        Model.ToList().ForEach(i =>
        {
            if (i.DealerName != null) 
            {
                Response.Write(((Func<dynamic, object>)(
                    @<text>
                        <b>Hello Dealer named: @item.DealerName
                        Multiline support is <em>Beautiful!</em>
                    </text>)).Invoke(i));
            }
        });
    }
    

    希望这是有道理的:)

    【讨论】:

    • 是的 Response.Write 有效,但对于更复杂的示例,字符串连接很快就会失控。 :(
    • 是的,你是对的..我已经更新了帖子以允许在这个函数中使用几乎任何类型的 Razor 代码.. 享受:)
    • 感谢您使用 Artiom 的麻烦。我特别喜欢你的多线技巧。不幸的是,我不能进入这样的代码块。正如我在问题中提到的,我需要在组件供应商 lambda 表达式中提供我的内容/模板来构建控件。 .ASPX 代码看起来很简单。我是否认为 Razor 不支持与 MVC .ASPX 代码相同级别的 lambda 表达式?
    • 等等.. 但是在您的 .aspx 示例中,您正在做同样的事情.. 您正在打开一个代码块,并在那里执行一个 .ForEach 方法.. 当然您应该能够在 Razor 控件中做同样的事情.. 至少我从来没有遇到过任何问题
    • Hmm.. 请注意,我认为不是每个人都知道您可以将@{ code goes here } 块放在剃须刀页面的任何位置,而不仅仅是作为 .cshtml 文件的“头”。事实上,如果您想在 aspx 中间运行 void 方法或创建新变量,您必须使用这样的代码块 :)
    【解决方案2】:

    或者,您可以创建一个 lambda 函数,并为 Razor 代码主体中的每个项目调用它(这个想法来自 this post 中的 Andy):

    @model IEnumerable<Dealer>
    
    @{
        Func<Dealer, object> sayHi = 
            @<text>
                 <b>Hello Dealer named: @(item.DealerName)</b>
                 Multiline support is <em>Beautiful!</em>
             </text>;
    }
    
    <div>
        @foreach(var dealer in Model.ToList())
        {
            sayHi(dealer);
        }
    </div>
    

    【讨论】:

      【解决方案3】:

      是的,它们受支持。但是,Razor 有一些奇怪的转义规则,额外的大括号有时会导致它阻塞,包括扩展 lambda 表达式中的那些。

      您可以稍微简化@Artioms 的答案,以使用 where 和可选的 select 子句删除那些额外的大括号

      @{
          Model.ToList().ForEach(i =>
          {
              if (i.DealerName != null) 
              {
                  Response.Write(i.DealerName);
              }
          });
      }
      

      变成

      @{
          Model.Where(i=>i.DealerName != null).ToList().ForEach(i =>
          {
                  Response.Write(i.DealerName);
          });
      }
      

      也可以变成

      @{Model.Where(i=>i.DealerName != null).Select(i=>i.DealerName)
          .ToList().ForEach(Response.Write);}
      

      是的功能样式!

      【讨论】:

      • 感谢您的反馈,但它没有回答问题。
      • 我对顶部进行了重新措辞,使其更加清晰 - 它改进了@Artioms 的答案。我还提供了另一种解决方法 - 删除可能会混淆剃刀编译器的额外大括号。我认为它至少很有用。
      猜你喜欢
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      相关资源
      最近更新 更多