我怎样才能建立一个“;循环“;Razor的助手
本文关键字:一个 循环 Razor 建立 | 更新日期: 2023-09-27 18:16:30
基本上,我想把这个助手添加到Razor中。我尝试过的:
public static class Html
{
static Dictionary<string[], int> _cycles;
static Html()
{
_cycles = new Dictionary<string[], int>();
}
public static string Cycle(this HtmlHelper helper, string[] options)
{
if (!_cycles.ContainsKey(options)) _cycles.Add(options, 0);
int index = _cycles[options];
_cycles[options] = (options.Length + 1) % options.Length;
return options[index];
}
用法:
<tr class="@Html.Cycle(new[]{"even","odd"})">
但它只是对每一排都说"偶数"。。。不知道为什么。我不确定这个类是什么时候实例化的。。。。。是每个请求一次,每个服务器运行一次。。。还是怎样不管我该如何解决这个问题,以便它给出预期的替换?
尝试#2
public static class Html
{
public static string Cycle(this HtmlHelper helper, params string[] options)
{
if(!helper.ViewContext.HttpContext.Items.Contains("cycles"))
helper.ViewContext.HttpContext.Items["cycles"] = new Dictionary<string[],int>(new ArrayComparer<string>());
var dict = (Dictionary<string[], int>)helper.ViewContext.HttpContext.Items["cycles"];
if (!dict.ContainsKey(options)) dict.Add(options, 0);
int index = dict[options];
dict[options] = (index + 1) % options.Length;
return options[index];
}
}
class ArrayComparer<T> : IEqualityComparer<T[]>
{
public bool Equals(T[] x, T[] y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
if (x.Length != y.Length) return false;
for (int i = 0; i < x.Length; ++i)
if (!x[i].Equals(y[i])) return false;
return true;
}
public int GetHashCode(T[] obj)
{
return obj.Length > 0 ? obj[0].GetHashCode() : 0;
}
}
这有什么问题吗?
之所以失败,是因为您每次都使用一个全新的数组作为字典的键。
我建议添加一个额外的参数作为dictionary键。
而且看在上帝的份上,请使用私人存储区。(而不是static
成员,当多个线程击中页面时,它会爆炸。(
对Cycle
方法的每次调用都会传递一个新的options
数组,向字典中添加一个新键。
要解决这一问题和线程问题,可以将字符串本身用作HttpContext:中的键
string key = "Cycle-"+String.Join("|", options);
if (!html.ViewContext.HttpContext.Items.Contains(key))
html.ViewContext.HttpContext.Items.Add(key, 0);
int index = html.ViewContext.HttpContext.Items[key];
html.ViewContext.HttpContext.Items[key] = (index + 1) % options.Length;
return options[index];
请注意,这将在子动作和部分之间共享循环。
我发现我也可以用@function
来完成。。。那么我不需要将名称空间添加到CCD_ 5。
@using MvcApplication4.Helpers @* for ArrayComparer *@
@functions {
public static string Cycle(params string[] options)
{
if (!HttpContext.Current.Items.Contains("Html.Cycle"))
HttpContext.Current.Items["Html.Cycle"] = new Dictionary<string[], int>(new ArrayComparer<string>());
var dict = (Dictionary<string[], int>)HttpContext.Current.Items["Html.Cycle"];
if (!dict.ContainsKey(options)) dict.Add(options, 0);
int index = dict[options];
dict[options] = (index + 1) % options.Length;
return options[index];
}
}
也可以用@helper
来做,但我认为它不会那么干净。