Искробезопасный синтаксис в Razor foreach - PullRequest
0 голосов
/ 26 июля 2011

Мы некоторое время использовали движок Spark View в нашем приложении. С момента выпуска Resharper 6 с его великолепной поддержкой Razor, мы обвалились и начали менять местами.

Одной из лучших частей Spark была его автоматическая генерация переменных внутри цикла foreach. Например, внутри цикла вы автоматически получаете переменные index, last и first, которые позволяют вам узнать индекс, является ли элемент первым элементом и является ли элемент последним элементом соответственно.

Мой вопрос заключается в следующем: есть ли способ, чтобы foreach автоматически генерировал эти переменные для меня, поэтому мне не нужно делать это вручную? Нужно ли мне создавать своего собственного помощника, который делает это?

Ответы [ 3 ]

1 голос
/ 28 июля 2011

Как и предполагал BuildStarted, я использовал пост Фила Хаака, чтобы сформулировать решение.

public static HelperResult Each<TItem>(this IEnumerable<TItem> items, Func<EnumeratedItem<TItem>, HelperResult> template)
{
    return new HelperResult(writer =>
            {
                int index = 0;
                ICollection<TItem> list = items.ToList();

                foreach (var item in list)
                {
                    var result = template(new EnumeratedItem<TItem>(index, index == 0, index == list.Count - 1, item));
                    index++;
                    result.WriteTo(writer);
                }
            });
}

И класс EnumeratedItem:

public class EnumeratedItem<TModel>
{
    public EnumeratedItem(int index, bool isFirst, bool isLast, TModel item)
    {
        this.Index = index;
        this.IsFirst = isFirst;
        this.IsLast = isLast;
        this.Item = item;
    }

    public int Index { get; private set; }
    public bool IsFirst { get; private set; }
    public bool IsLast { get; private set; }
    public TModel Item { get; private set; }
}

Я был вынужден преобразовать IEnumerable в ICollection, чтобы получить свойство Count.

Использование:

@Model.History.Each(
    @<text>
        <li class="@(@item.IsLast ? "last" : string.Empty)">
        @{ var versionNo = Model.History.Count - @item.Index; }
        <div class="clearfix version selected">
            <div class="index">
                <a href="@item.Item.Url">@versionNo</a>
            </div>
            <div class="modified">
                @item.Item.DateModified<br/>
                @Html.Raw(item.Item.ModifiedBy)
            </div>
            <div class="view">
                <a href="@item.Item.CompareUrl">View changes</a>
            </div>
        </div>
    </li>
    </text>)
0 голосов
/ 26 июля 2011

Фил Хаак написал хороший пример, который даст вам предметы, которые вы ищете здесь http://haacked.com/archive/2011/04/14/a-better-razor-foreach-loop.aspx

Это не то же самое, что foreach, однако вам потребуется сделать что-то подобное, если вы хотите функции, которые вы ищете.

HugoWare также написал отличную статью для IEnumerable расширений, которая предоставляет всю необходимую функциональность http://hugoware.net/blog/build-a-smarter-loop-with-c

Я бы, вероятно, рекомендовал использовать пример Hugoware, так как это больше, чем просто бритва.

0 голосов
/ 26 июля 2011

В Visual Studio 2010 есть «фрагменты кода» - части кода, которые позволяют генерировать код. с помощью некоторых утилит вы можете отредактировать фрагмент по умолчанию для «foreach» и написать собственный код с нужными вам переменными.

...