/ / Razorの「サイクル」ヘルパーを作成するにはどうすればよいですか? -C#、asp.net-mvc-3、カミソリ、サイクル、ヘルパー

Razor用の「サイクル」ヘルパーを作成するにはどうすればいいですか? - c#、asp.net-mvc-3、かみそり、サイクル、ヘルパー

基本的に、追加したい この助っ人 かみそりに。私が試したもの:

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"})">

しかし、すべての行で「偶数」と表示されます... なぜかわからない。このクラスがインスタンス化されるタイミングがわかりません。....リクエストごと、サーバー実行ごとに1回...または何ですか?それでも...これを修正して、意図した代替を与えるにはどうすればよいですか?


試み#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;
}
}

これで何か問題がありますか?

回答:

回答№1は2

これが失敗する理由は、毎回辞書のキーとして新しい配列を使用しているためです。

追加のパラメーターを追加して、ディクトナリーキーとして使用することをお勧めします。

そして たのむよ、専用のストレージエリアを使用してください。 (ではなく static メンバー。複数のスレッドがページにヒットすると爆発します。)


回答№2の場合は1

あなたへのすべての呼び出し Cycle メソッドは新しい options 配列、新しいキーを辞書に追加します。


回答№3の場合は1

この問題とスレッドの問題の両方を修正するには、文字列自体を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];

これは、子アクションとセクション全体でサイクルを共有することに注意してください。


回答№4の場合は0

私はこれを行うことができると考えました @function また...名前空間を追加する必要はありません 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];
}
}

また、それを行うことができます @helper しかし、私はそれがそれほどきれいだとは思わない。