从ASP.NET 2.0(VB)到MVC 3(C#),我对用于View的语法感到非常困惑。
@Html.LabelFor(m => m.UserName)
那是从哪里来的?我唯一的猜测是它代表了传递给视图的模型。我尝试将m更改为c,它仍然可以正常工作。
语法的一部分是否涉及“=>”更多的MVC,C#或Razor元素?
答案 0 :(得分:10)
m
来自哪里?
它是lambda表达式中的参数。
我唯一的猜测是它代表了传递给视图的模型。我尝试将m更改为c,它仍然可以正常工作。
那是因为名字并不重要。它只是一个参数名称,它实际上并不是指任何现有变量。
语法的一部分是否涉及“=>”更多的MVC,C#或Razor元素?
它是C#,但LabelFor
使用编译器转换m => m.UserName
的内容来提取构建标签所需的内容。
这是一个非常复杂的主题。我建议你找一本你觉得很舒服的书(例如,深度的C#在这个问题上非常好)来了解更多。您想要阅读有关lambda表达式和表达式树的信息。
答案 1 :(得分:8)
这是自C#3.0以来一直存在的语法技巧(我认为;可能是3.5)。
如果您要在代码中编写此代码(并且您的Razor视图在编译之前确实已转换为C#代码文件,因此代码中确实 ),编译器有两种可能的方式根据上下文编译它。
如果方法LabelFor()
需要委托,则将其编译为匿名方法。或者,如果方法需要System.Linq.Expressions.Expression<Func>
类型,则构造expression tree。这就是你的情况。
这种令人沮丧的语法的原因是表达式树包含足够的信息,(与Reflection结合使用)LabelFor()
方法可以提取您所引用的实际属性。如果您只是将其作为LabelFor(Model.UserName)
传递,则LabelFor()
没有足够的信息来执行此操作。它只会从UserName
属性中获取值。但现在它知道它来自哪里,并且可以使用更多的反射来浏览属性的属性。属性,例如DisplayFormat
,Required
和其他。
m
(或c
或其他)实际上是您的模型。 LabelFor
是一种扩展方法,它只是将模型传递回Lambda表达式,这样整个表达式树技巧就可以工作了。您也可以像LabelFor(x=>Model.UserName)
那样编写它,但我认为它不会起作用(我没试过,也许它确实如此)。
答案 2 :(得分:3)
这是一个Lambda表达式,link。
交易是这样的:m是一个变量,它在给定的环境中接收模型的实例 在labelFor中,它将调用一个编译时创建的类,它有一个方法可以将你作为参数传递给LabelFor。
一个lambda表达式可以由一个委托切换,结果完全相同,除了次要的,非常小的性能提升,一次。
一般的想法是你传递一个方法在LabelFor方法的某处执行。
例如: 方法:
public void Dummy(Action<string> action)
{
if(iFeelLikeIt) {action("I feel Like it");}
}
应该用作:
Dummy(msg => MessageBox.Show(msg));
答案 3 :(得分:1)
这是 Lambda Expression 。来自MSDN:
lambda表达式是一个匿名函数,可以包含表达式和语句,可用于创建委托或表达式树类型。
所有lambda表达式都使用lambda operator =&gt;,它被读作“转到”。 lambda运算符的左侧指定输入参数(如果有),右侧包含表达式或语句块。 lambda表达式x =&gt; x * x读作“x转到x乘x。”
答案 4 :(得分:0)
LabelFor是一个Razor函数,它在内部具有Model的知识。换句话说,模型驻留在LabelFor函数逻辑内。传递lambda表达式时,您将匿名函数传递给LabelFor,因此它知道如何处理其内部Model对象以提取信息。
通常,您将传递Model作为参数,LabelFor将使用内部逻辑来提取所需的信息。但在这种形式下,情况正好相反。 LabelFor在内部知道参数(模型),但它不知道如何处理它。你告诉它通过传递Lambda函数做什么。
运行代码时,将Lambda表达式作为参数传递给LabelFor。 LabelFor,获取lambda表达式并将其传递给Model对象的内部副本。 Lambda表达式返回Model对象的UserName属性,LabelFor使用它来构建HTML代码。