C# 我怎样才能建立一个;循环;剃刀助手?

C# 我怎样才能建立一个;循环;剃刀助手?,c#,asp.net-mvc-3,razor,cycle,helpers,C#,Asp.net Mvc 3,Razor,Cycle,Helpers,基本上,我想添加到剃须刀。我尝试的是: public static class Html { static Dictionary<string[], int> _cycles; static Html() { _cycles = new Dictionary<string[], int>(); } public static string Cycle(this HtmlHelper helper, string[

基本上,我想添加到剃须刀。我尝试的是:

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];
    }
公共静态类Html
{
静态字典循环;
静态Html()
{
_循环=新字典();
}
公共静态字符串循环(此HtmlHelper帮助程序,字符串[]选项)
{
如果(!_cycles.ContainsKey(选项))_cycles.Add(选项,0);
整数索引=_周期[选项];
_循环[选项]=(options.Length+1)%options.Length;
返回选项[索引];
}
用法:

<tr class="@Html.Cycle(new[]{"even","odd"})">

但它只是对每一行说“偶数”…不确定为什么。我不确定这个类何时被实例化…是每个请求一次,每个服务器运行一次…还是什么?不管怎样…我如何修复它,以便它提供预期的替换


尝试#2
公共静态类Html
{
公共静态字符串循环(此HtmlHelper帮助程序,参数字符串[]选项)
{
如果(!helper.ViewContext.HttpContext.Items.Contains(“cycles”))
helper.ViewContext.HttpContext.Items[“cycles”]=new Dictionary(new ArrayComparer());
var dict=(Dictionary)helper.ViewContext.HttpContext.Items[“cycles”];
如果(!dict.ContainsKey(options))dict.Add(options,0);
int index=dict[options];
dict[options]=(索引+1)%options.长度;
返回选项[索引];
}
}
类阵列比较程序:IEqualityComparer
{
公共布尔等于(T[]x,T[]y)
{
if(ReferenceEquals(x,y))返回true;
如果(x==null | | y==null)返回false;
如果(x.Length!=y.Length)返回false;
对于(int i=0;i0?obj[0].GetHashCode():0;
}
}

有什么问题吗?

每次调用
循环
方法都会传递一个新的
选项
数组,向字典中添加一个新键。

每次调用
循环
方法都会传递一个新的
选项
数组,向字典中添加一个新键。

失败的原因是因为您使用的是一个品牌每次都将新数组作为字典的键

我建议只包含一个额外的参数,用作口述键


看在上帝的份上,请使用一个私有存储区(而不是一个静态的
成员,当多个线程到达页面时,它会爆炸)。

失败的原因是,每次都使用一个全新的数组作为字典的键

我建议只包含一个额外的参数,用作口述键


看在上帝的份上,请使用一个私有存储区(而不是一个
静态
成员,当多个线程到达页面时,该成员将爆炸)。

要解决这一问题和线程问题,您可以将字符串本身用作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];

请注意,这将在子操作和部分之间共享周期。

要解决此问题和线程问题,可以将字符串本身用作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];

请注意,这将在子操作和部分之间共享周期。

发现我也可以使用
@函数来实现这一点。
那么我就不需要将名称空间添加到
Web.config

@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];
    }
}
@为ArrayComparer使用MVCAPApplication4.Helpers@**@
@功能{
公共静态字符串循环(参数字符串[]选项)
{
如果(!HttpContext.Current.Items.Contains(“Html.Cycle”))
HttpContext.Current.Items[“Html.Cycle”]=新字典(new ArrayComparer());
var dict=(Dictionary)HttpContext.Current.Items[“Html.Cycle”];
如果(!dict.ContainsKey(options))dict.Add(options,0);
int index=dict[options];
dict[options]=(索引+1)%options.长度;
返回选项[索引];
}
}

也可以使用
@helper
来完成,但我认为它不会那么干净。

我想我也可以使用
@函数来完成……然后我不需要将名称空间添加到
Web.config

@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];
    }
}
@为ArrayComparer使用MVCAPApplication4.Helpers@**@
@功能{
公共静态字符串循环(参数字符串[]选项)
{
如果(!HttpContext.Current.Items.Contains(“Html.Cycle”))
HttpContext.Current.Items[“Html.Cycle”]=新字典(new ArrayComparer());
var dict=(Dictionary)HttpContext.Current.Items[“Html.Cycle”];
如果(!dict.ContainsKey(options))dict.Add(options,0);
int index=dict[options];
dict[options]=(索引+1)%options.长度;
返回选项[索引];
}
}

也可以使用
@helper
来完成,但我认为它不会那么干净。

如果使用多个线程,您的代码将严重失败。请使用
helper.ViewContext.HttpContext.Items
。只是一个小建议:使用
params
数组。
公共静态字符串循环(此HtmlHelper,params string[]选项)
这将允许您在不使用
新[]{…}
部分的情况下调用函数。相反,您只需使用
@Html.Cycle(“偶数”、“奇数”)
@JohnGietzen:对!我没有想到使用params。那更好。@SLaks:是的……我认为可能存在线程问题,但我不知道如何解决这个问题。在您的更新版本中:我会在将数组用作字典键之前克隆它(因为这样可以防止有人修改数组时出现奇怪的行为)。接下来,我建议使用
Dictionary.TryGetValue
,而不是
Dictionary.ContainsKey
,因为它只允许检查一次。除此之外,这似乎工作得很好。您的代码将在多个线程中严重失败。请使用
helper.ViewContext.HttpContext.Items
。只需进行一次小的重新设置推荐:使用
params
数组。
public static str