gpt4 book ai didi

.net - Razor 中优雅的 foreach - else 构造

转载 作者:行者123 更新时间:2023-12-02 13:21:36 24 4
gpt4 key购买 nike

许多模板引擎都有一种特殊的语法,它是 foreachelse 的组合。基本上,当 foreach 循环没有任何迭代时,就会执行 else 子句。如果您想显示某种列表中没有项目的后备,这会很有用。

Twig例如,for loop可以看起来像这样

{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no user found</em></li>
{% endfor %}

使用 Razor View Engine,模板会像这样,涉及对集合中项目数量的额外检查:

@foreach (var user in users) {
<li>@user.UserName</li>
}
@if (!users.Any()) {
<li><em>no user found</em></li>
}

所以我的问题是:我们能否使用 Razor View Engine 以某种方式实现类似的优雅。

最佳答案

整合 Jamiec 和 Martin Booth 的答案。我创建了以下扩展方法。它采用 IEnumerable 作为第一个参数,然后使用两个委托(delegate)来呈现文本。在 Razor View 中,我们可以传入模板化委托(delegate)两个这样的参数。简而言之,这意味着您可以提供模板。这是扩展方法以及如何调用它:

    public static HelperResult Each<TItem>(this IEnumerable<TItem> items, 
Func<TItem, HelperResult> eachTemplate,
Func<dynamic, HelperResult> other)
{
return new HelperResult(writer =>
{
foreach (var item in items)
{
var result = eachTemplate(item);
result.WriteTo(writer);
}

if (!items.Any())
{
var otherResult = other(new ExpandoObject());
// var otherResult = other(default(TItem));
otherResult.WriteTo(writer);
}
});
}

在 Razor View 中:

@Model.Users.Each(
@<li>@item.Name</li>,
@<li>
<b>No Items</b>
</li>
)

总而言之,非常干净。

更新实现评论中提出的建议。此扩展方法采用一个参数来循环集合中的项目并返回一个自定义 HelperResult。在该 helperresult 上,可以调用 Else 方法来传入模板委托(delegate),以防找不到任何项目。

public static class HtmlHelpers
{
public static ElseHelperResult<TItem> Each<TItem>(this IEnumerable<TItem> items,
Func<TItem, HelperResult> eachTemplate)
{
return ElseHelperResult<TItem>.Create(items, eachTemplate);
}
}

public class ElseHelperResult<T> : HelperResult
{
private class Data
{
public IEnumerable<T> Items { get; set; }
public Func<T, HelperResult> EachTemplate { get; set; }
public Func<dynamic, HelperResult> ElseTemplate { get; set; }

public Data(IEnumerable<T> items, Func<T, HelperResult> eachTemplate)
{
Items = items;
EachTemplate = eachTemplate;
}

public void Render(TextWriter writer)
{
foreach (var item in Items)
{
var result = EachTemplate(item);
result.WriteTo(writer);
}

if (!Items.Any() && ElseTemplate != null)
{
var otherResult = ElseTemplate(new ExpandoObject());
// var otherResult = other(default(TItem));
otherResult.WriteTo(writer);
}
}
}

public ElseHelperResult<T> Else(Func<dynamic, HelperResult> elseTemplate)
{
RenderingData.ElseTemplate = elseTemplate;
return this;
}

public static ElseHelperResult<T> Create(IEnumerable<T> items, Func<T, HelperResult> eachTemplate)
{
var data = new Data(items, eachTemplate);
return new ElseHelperResult<T>(data);
}

private ElseHelperResult(Data data)
: base(data.Render)
{
RenderingData = data;
}

private Data RenderingData { get; set; }
}

然后可以按如下方式调用:

@(Model.Users
.Each(@<li>@item.Name</li>)
.Else(
@<li>
<b>No Users</b>
</li>
)
)

关于.net - Razor 中优雅的 foreach - else 构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7820117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com