Являются ли лямбда-выражения поддерживаемыми Razor?

17

Поддерживаются ли лямбда-выражения / анонимные методы в механизме просмотра 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%> <%
           };
       }); 
%>

Это для механизма Razor, который поставляется с ASP.NET MVC3.

    
задан Philip Fourie 08.02.2011 в 01:41
источник

3 ответа

11

Вместо блока <text>@i.DealerName</text> вы можете использовать Response.Write(i.DealerName);

Результат будет таким же, как если бы вы отбросили его на странице Razor - он будет выполняться на странице рендеринга .. И, честно говоря, я уверен, что это то, во что оно будет скомпилировано.

Кроме того, поскольку ForEach() возвращает void, вам придется отбросить его на странице как блок кода. Таким образом, ваш код будет выглядеть примерно так:

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

UPD: Если у вас есть более серьезное форматирование, вы можете прибегнуть к этому приятному маленькому трюку:
(к сожалению, краска кода здесь не даст этому фрагменту никакого кредита, но вы определенно увидите, что я имею в виду, если вы отбросите это в 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));
        }
    });
}

Надеюсь, что это имеет смысл:)

    
ответ дан Artiom Chilaru 08.02.2011 в 02:08
  • Да Response.Write работает, но для более сложного примера строка конкатенации выходит из-под контроля очень быстро. :( –  Philip Fourie 08.02.2011 в 02:11
  • Да, вы правы. Я обновил сообщение, чтобы разрешить практически любой вид кода Razor внутри этой функции. Наслаждайтесь :) –  Artiom Chilaru 08.02.2011 в 02:27
  • Спасибо за твои проблемы, ты взял Артёма. Мне особенно нравится ваш многолинейный трюк. К сожалению, я не могу попасть в блок кода, подобный этому. Как я уже упоминал в своем вопросе, мне нужно предоставить свой контент / шаблон внутри выражения lambda поставщиков компонентов, чтобы создать элемент управления. Это выглядит так просто в коде .ASPX. Должен ли я считать, что лямбда-выражения не поддерживаются в Razor на том же уровне, что и для кода MVC .ASPX? –  Philip Fourie 08.02.2011 в 02:39
  • Подождите .., но в вашем примере .aspx вы делаете то же самое. Вы открываете блок кода, и вы выполняете метод .ForEach. Конечно, вы должны иметь возможность просто делать то же самое в контроле Razor. По крайней мере, у меня никогда не было никаких проблем, связанных с этим –  Artiom Chilaru 08.02.2011 в 02:43
  • Хм .. Просто примечание, я думаю, не все знают, что вы можете разместить блок @ {код здесь} в любом месте на странице бритвы, а не только как «голова» файла .cshtml. На самом деле вам нужно использовать такие блоки кода, как это, если вы хотите запускать методы void в середине aspx или создавать новые переменные :) –  Artiom Chilaru 08.02.2011 в 02:47
Показать остальные комментарии
2

В качестве альтернативы вы можете создать лямбда-функцию и вызвать ее для каждого элемента в теле вашего кода 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>
    
ответ дан Matt 05.03.2012 в 23:22
1

Да, они поддерживаются. НО, у Razor есть некоторые странные правила экранирования, и дополнительные фигурные скобки заставят его задушить иногда, в том числе в расширенных выражениях лямбда.

Вы можете упростить @Artioms немного ответить, чтобы удалить лишние фигурные скобки, где и, возможно, предложение 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);}

Функциональные стили Yay!

    
ответ дан scaryman 17.09.2012 в 19:19
  • Спасибо за отзыв, но он не отвечает на вопрос. –  Philip Fourie 18.09.2012 в 09:51
  • Я переработал верх, чтобы быть более понятным - он улучшает ответ @Artioms. Я также предоставил другое обходное решение - удаление дополнительных брекетов, которые потенциально могут смутить компилятор бритвы. Я думаю, что это полезно, по минимуму. –  scaryman 18.09.2012 в 15:24