MVC中的@ Html.EditorFor(m => m)lambda语法

时间:2012-05-06 00:15:29

标签: c# razor lambda extension-methods editorfor

我只是在学习C#和MVC,并试图了解一些例子。

@Html.EditorFor(m => m)

最终我发现'=>'是lambda运算符,它意味着像“m这样的m”。这对我来说没有任何意义。为什么不直接传入?

另外,我没有看到m在我正在使用的任何视图中定义。定义了模型,据称这就是这种方法所采用的方法。这有什么作用?

最后,我查看了Html.EditorFor的定义,并没有看到只传递一个参数的任何重载。这个语法定义在哪里? http://msdn.microsoft.com/en-us/library/ee834942.aspx

4 个答案:

答案 0 :(得分:18)

让我们通过检查方法签名来解决这个问题:

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

这是使用扩展方法语法,这意味着它正在向EditorFor添加名为HtmlHelper的方法,以便您可以进行调用Html.EditorFor。但我们真正感兴趣的是第二个参数Expression<Func<TModel, TValue>>。这是一个非常复杂的参数,但是现在我们可以忽略它是Expression的事实。如此简化,让我们来看看:

Func<TModel, TValue> expression

这意味着参数是任何方法,它有一个参数(类型为TModel),返回类型为TValue。你一直在使用lambdas,它(基本上)是一个方法的更简洁的表示,但将它想象成一个普通的方法是有帮助的。所以你是lambda正在拿一个模型并返回一个模型:

m => m

这不是那么有趣,所以让我们将它与一个更现实的场景进行比较,你将从模型中返回一个属性:

m => m.MyStringProperty

现在让我们将它与您在某处声明的普通静态方法进行比较:

public static class MyStaticClass 
{
    public static string Foo(TModel model) 
    {
        return model.MyStringProperty;
    }
}

虽然真的在这里它不会是TModel - 但是你通过@model声明了你的模型类型。现在,为了便于讨论,您可以在调用EditorFor时使用此方法:

Html.EditorFor(MyStaticClass.Foo);

总而言之,lambdas(在大多数情况下)只是常规方法的一小部分。所以你所做的只是传递方法。

这里最后一个注意事项是我们实际上正在使用表达式树,这意味着您实际上没有传递方法,而是传递一个表示方法代码的对象模型(表达式树)。实际上,这只是用来计算你正在使用的属性名称(因为lambda通常更像m => m.MyProperty,而不仅仅是m => m)。这是为了避免使用字符串(即“MyProperty”)引用属性名称的魔术字符串。

答案 1 :(得分:3)

  1. 在您的示例中,lambda函数不起任何作用,是真的。但它的真正用途是当您想要为模型的属性渲染编辑器时:@ Html.EditorFor(m =&gt; m.SomeProperty)。 Lambda表达式实际上只是函数的简写,但通过delegates强类型化。 Javascript中的概念可能更为熟悉:

    myFunction(function(x){return x.SomeProperty;});

  2. &#34; m&#34;没有预定义。它为lambda表达式的第二部分命名参数,可以是任何东西:@ Html.EditorFor(无论是什么=&gt;等等)。 (它指的是相同的东西,在这种情况下是页面的模型,不管你的名字是什么。)

  3. 您在Html.EditorFor的定义中看到的第一个参数并不是一个真正的参数。您会注意到他们正在使用关键字来定义extension methods。该参数引用调用该方法的对象,在本例中为 HtmlHelper&lt; Model&gt; 对象。

答案 2 :(得分:2)

<强> 1

  • @Html.EditorFor(m => m) - 整个模型的显示编辑器
  • @Html.EditorFor(m => m.propertyName) - 显示模型特定属性的编辑器

<强> 2

@Html.EditorFor(m => m)等于@Html.EditorFor(t => t)@Html.EditorFor(randomName => randomName)。名称无关紧要,只是参数的名称。此参数的类型是视图模型的类型。

你必须传递功能,因为它不仅仅是价值,而且很重要。反射用于获取描述如何显示属性的属性。看看这个例子

public class ResetPasswordModel
{
    public string Username { get; set; }

    [DataType(DataType.Password)]
    public string NewPassword { get; set; }
    [DataType(DataType.Password)]
    public string PasswordConfirmed { get; set; }
}

属性描述,NewPassword应该是密码字段,而不是常规输入。如果我们通过了价值,那是不可能的。

在我们的示例中,@Html.EditorFor(m => m)将显示包含一个用户名输入和两个密码密码输入。 @Html.EditorFor(m => m.NewPassword)将显示输入,其中包含密码类型。

第3

http://msdn.microsoft.com/en-us/library/ee402949.aspx

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

这是HtmlHelper类的扩展方法。 this HtmlHelper<TModel> html不是参数,它是类的类型,函数扩展。

答案 3 :(得分:1)

=>运算符视为“转到”的含义,因此(m => m)表示“m转到m”,另一种说法是回到同一事物m。< / p>

在您的示例中,@Html.EditorFor(m => m)m是lambda表达式m => m的匿名输入参数,它是扩展方法EditorFor的参数。正如您在问题中所指出的,此方法的重载都不会超过单个参数;这是因为它是Extension Method,第一个参数表示它扩展的类型。第二个参数是Expression,您可以使用lambda 表达式