6

次のようなモデルがあるとします。

class Foo
{
    public int A {get; set;}
    public int B {get; set;}
}

class SomeModel
{
    public List<Foo> Foos { get; set; }

}

ASP.NET mvcフレームワークのかみそりビューでは、次の操作を実行できます。

@model SomeModel

@for(int i = 0; i < Model.Foos.Count; ++i)
{
   Html.EditorFor(x => x.Foos[i]);
}

そして、レイザーエンジンは、インデックスを含む正しいhtmlをうまく吐き出し、正しいインデックス付きインスタンスを使用してエディターテンプレートを呼び出します。

EditorForメソッドは、署名付きの静的拡張メソッドです

public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)

シグニチャから、それが単に式を取っていることは明らかであり、唯一のコンテキストはHtmlHelperインスタンスから来ています。

私は非常に限られたExpressionツリー処理を実行しましたが、私が見たものから、この静的メソッドが何らかの形で魔法のように取得している情報を知ることができる方法はわかりません。

このメソッドは、HTML名を生成するためのインデックスをどのようにEditorFor把握し、エディターテンプレートに渡す正しいインスタンスを取得できますか?

4

1 に答える 1

6

の値ではなく、式を渡していますx.Foos[i]。次に、MVCはその式を評価し、インデックス付きのコレクションを指定したことを確認します。ループ全体を削除して次のことを行った場合も、同じ結果が得られます。

Html.EditorFor(x => x.Foos)

MVCは、コレクションのすべての要素のエディターテンプレートを自動的にレンダリングし、適切な名前を生成します。

MVCがディスプレイ/エディターテンプレートを処理する方法の詳細については、こちらをご覧ください:リンク

編集:これが実際に動作していることを確認するために、私が走り書きしたランダムなコードを次に示します。

List<string> list = new List<string>() { "A", "B", "C" };
var tester = new ExpressionTester<List<string>>(list);
var item = tester.Foo(p => p[0]);

次のクラスも必要です。

public class ExpressionTester<TModel>
{
    private TModel _list;
    public ExpressionTester(TModel list)
    {
        _list = list;
    }

    public TValue Foo<TValue>(Expression<Func<TModel, TValue>> expression)
    {
        var func = expression.Compile();
        return func.Invoke(_list);
    }
}

Foo()にブレークポイントを設定しexpression、デバッグでパラメーターを確認します。[本文]->[引数]の下に、式で渡したインデックスがあります。Body-> Methodの下に、それが実際には一般的なリストであることがわかります。

于 2013-02-02T07:14:46.533 に答える