Razor支持Lambda表达式吗?

18

lambda表达式/匿名方法在Razor视图引擎中受支持吗?

我在Razor中遇到了困难,无法表达以下内容:

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

注意: 我知道可以用@foreach解决这个问题,但我需要一个类似的解决方案来处理第三方MVC控件。它使用这种机制来设置控件的内容。对于MVC .ASPX视图,它运行良好,但无法让它在Razor中工作。


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

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

这是为ASP.NET MVC3随附的Razor引擎。

3个回答

11

你可以使用 Response.Write(i.DealerName); 替换你的 <text>@i.DealerName</text> 块。

结果是相同的,就好像你将其放在Razor页面中一样 - 它将在呈现页面时执行。而且,实际上 - 我非常确定这就是它最终编译成的形式。

另外,由于 ForEach() 返回 void,因此您必须将其放在页面中作为代码块。 所以你的代码应该长这样:

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

更新:如果你有更复杂的格式要求,你可以使用这个小技巧:
(不幸的是,这里的代码颜色并不能使这个片段获得任何信誉,但是如果你将其放入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 可以工作,但对于更复杂的示例,字符串连接会很快失控。 :( - Philip Fourie
感谢您为此付出的努力,Artiom。我特别喜欢你的多行技巧。不幸的是,我无法像这样进入代码块。正如我在问题中所提到的,我需要在组件供应商的Lambda表达式内提供我的内容/模板以构建控件。在.ASPX代码中似乎很简单。我该怎么理解,Razor与MVC .ASPX代码相比不支持Lambda表达式的同一级别呢? - Philip Fourie
那就是问题所在。它在Razor中无法工作(至少对我来说是这样)。根据我的发现,当在lambda表达式内部时,编译器似乎无法确定代码/HTML的起始位置。 - Philip Fourie
嗯..你能给我一个例子,说明razor解析器出现问题的地方吗?因为我提供的例子在测试页面上看起来都工作正常... - Artiom Chilaru
谢谢,现在它可用了。不幸的是,我必须弄清楚是否能够进入组件供应商的 lambda 表达式。再次感谢您的帮助。 - Philip Fourie
显示剩余10条评论

3

或者,您可以创建一个Lambda函数,并在Razor代码的主体中为每个项目调用该函数(这个想法来自这篇文章中的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>

1

是的,它们得到支持。但是,Razor有一些奇怪的转义规则,有时会导致其出现故障,包括扩展Lambda表达式中的花括号。

您可以通过使用where和可选的select子句来简化@Artioms的答案,以删除那些额外的花括号。

@{
    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);}

功能风格太棒了!


感谢您的反馈,但它并没有回答我的问题。 - Philip Fourie
我重新修改了顶部的内容,使其更加清晰易懂 - 这比@Artioms的答案更好。我还提供了另一种解决方法 - 删除可能会混淆Razor编译器的额外括号。我认为这至少是有用的。 - scaryman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接