2011-07-20 27 views
9

ASP.NET 2.0(VB)からMVC 3(C#)に移行すると、ビューに使用されている構文が非常に混乱しています。構文の質問:@ Html.LabelFor(m => m.UserName)

@Html.LabelFor(m => m.UserName) 

どこから来たのですか?私の唯一の推測は、それがビューに渡されているモデルを表しているということです。私はmをcに変更しようとしましたが、それでも正常に動作します。

MVC、C#、またはRazor要素の「=>」を含む構文の一部ですか?

+0

@NoProblemBabe、ここでそれをやっている人がいます:http://stackoverflow.com/questions/2595947/asp-net-mvc-label-for –

答えて

9

public void Dummy(Action<string> action) 
{ 
    if(iFeelLikeIt) {action("I feel Like it");} 
} 

として使用されるべきか?

ラムダ式のパラメータです。

私が推測するのは、ビューに渡されるモデルを表すということだけです。私はmをcに変更しようとしましたが、それでも正常に動作します。

これは名前が重要でないためです。それは単なるパラメータ名であり、実際には既存の変数を参照するものではありません。

MVC、C#、またはRazor要素の「=>」をより多く含む構文の部分はありますか?

これは、C#ですが、LabelForは、コンパイラが、それはラベルを構築するために必要なものを抽出するためにm => m.UserNameを変換するもの使用しています。

これは非常に深い複雑な対象です。快適な本を見つけることをお勧めします(詳細については、このトピックではC#の深さが非常に良いなど)。ラムダ式と式ツリーについて読んでみたい。

+0

私は彼がそれのための本を必要としません。 – Tocco

+1

+1 C#で深く - Jon Skeetはあなたを愛しています... –

3

これはラムダ式、linkです。

これは次のとおりです。mは、与えられた回覧でモデルのインスタンスを受け取る変数です。
labelForの内部では、コンパイル時に作成されたクラスが呼び出されます。このクラスには、LabelForに引数として渡したものを実行するメソッドがあります。

ラムダ式はデリゲートによって切り替えることができますが、実際にはマイナーなパフォーマンス向上を除いて全く同じ結果が得られます。

一般的な考え方は、LabelForメソッドのどこかで実行されるメソッドを渡すことです。

例: 方法:

mから来たことを
Dummy(msg => MessageBox.Show(msg)); 
1

ラムダ式です。 MSDN
ラムダ式は、式とステートメントを含むことができる無名関数であり、デリゲートまたは式ツリータイプの作成に使用できます。

すべてのラムダ式は、ラムダ演算子=>を使用します。これは、「行く」と解釈されます。ラムダ演算子の左辺は入力パラメータ(存在する場合)を指定し、右辺は式または文ブロックを保持します。ラムダ式x => x * xは、 "xはx回xに移動する"と読み込まれます。

8

これはC#3.0以降に存在する構文トリックです(私はおそらく3.5かもしれません)。

コンパイルする前にRazorビューをC#コードファイルに変換すると、実際にになります)、コンパイラは次の2つの方法でコンパイルできます文脈

LabelFor()メソッドがデリゲートを必要とする場合は、匿名メソッドにコンパイルされます。あるいは、メソッドがSystem.Linq.Expressions.Expression<Func>タイプを予期する場合、expression treeが構築されます。これはあなたの場合に起こっていることです。

このconvul​​ted構文理由は、式ツリーは、実際のプロパティを抽出することができる(リフレクションと組み合わせて)LabelFor()方法は、あなたが参照しているために十分な情報が含まれていることです。 LabelFor(Model.UserName)のように単純に渡す場合は、LabelFor()でこれを行うには十分な情報がありません。それはちょうどUserNameのプロパティから値を取得します。しかし今、それはどこから来たのかを知っていて、もっと多くのReflectionを使ってプロパティの属性を見ることができます。 DisplayFormat,Requiredなどの属性。

m(またはcなど)は実際のモデルです。 LabelForは拡張メソッドであり、モデルをラムダ式に戻すだけで、式ツリー全体が機能するようになります。 LabelFor(x=>Model.UserName)のように書くこともできますが、私はそれがうまくいくとは思えません。

+0

ああ、拡張構文の背後にある理由を説明してくれてありがとう。 – rkw

+0

ラムダ式は構文トリックですか?彼らは本当に重要な言語機能です! –

+0

はい。それは本当に重要な構文トリックです。 :) OK、まあ、私は多くの言語機能は "構文トリック"と呼ばれることができると思います。私はこの言葉を「書くのがずっと面倒であることを除けば、この機能を使わずにできること」を意味するのに使います。例えば、ラムダ式 'x => x * 2'は古代の' delegate(int x){return x * 2; } '構文です。あるいは、 'Expression 'を構築するために使用するならば、明示的な 'Expression'メソッドを使ってツリーを構築することができます。もちろん、コードは役に立たないところまで面倒になります。しかしそれはまだできます。 –

0

LabelForはモデルの知識を内部的に持つRazor関数です。言い換えれば、モデルはLabelFor関数ロジックの内部にあります。ラムダ式を渡すと、匿名関数をLabelForに渡します。そのため、内部モデルオブジェクトを使って情報を抽出する方法を知ることができます。

通常、パラメータとしてModelを渡し、LabelForは内部ロジックを使用して必要な情報を抽出します。しかし、この形式では、それは逆です。 LabelForはパラメータを内部的に(モデル)知っていますが、それをどうするかはわかりません。ラムダ関数を渡すことによって何をすべきかを教えてください。

コードを実行すると、LabelForにパラメータとしてラムダ式を渡します。 LabelForは、ラムダ式を受け取り、それにModelオブジェクトの内部コピーを渡します。 Lambda式はModelオブジェクトのUserNameプロパティを返し、LabelForはHTMLコードを作成するためにこのオブジェクトを使用します。