13

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

@Html.EditorFor(m => m)

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

此外,我没有在我正在使用的任何视图中定义 m 。模型已定义,据称这就是此方法所采用的方法。这是如何运作的?

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

4

4 回答 4

18

让我们通过检查方法签名来分解它:

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

这是使用扩展方法语法,这意味着它添加了一个名为EditorForto的方法HtmlHelper,以便您可以进行调用Html.EditorFor。但我们真正感兴趣的是第二个参数Expression<Func<TModel, TValue>>. 这是一个相当复杂的参数,但现在我们可以忽略它是一个Expression. 所以简化,让我们检查一下:

Func<TModel, TValue> expression

这意味着参数是具有一个参数(类型为)且返回类型为的任何方法。您一直在使用 lambda,它(本质上)是一种更简洁的方法表示,但将其视为普通方法会很有帮助。所以你是 lambda 正在接受一个模型并返回一个模型:TModelTValue

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”)引用属性名称的魔术字符串。

于 2012-05-06T00:29:52.037 回答
3
  1. 在您的示例中, lambda 函数没有任何用途,是的。但它的真正用途是当您想要为模型的属性呈现编辑器时:@Html.EditorFor(m => m.SomeProperty)。Lambda 表达式实际上只是函数的简写,但通过委托进行强类型化。这个概念在 Javascript 中可能更熟悉:

    我的功能(函数(x){返回x.SomeProperty;});

  2. “m”不是预定义的。它为 lambda 表达式的第二部分命名参数,可以是任何东西:@Html.EditorFor(whatever => whatever)。(它指的是同一个东西,在这种情况下是页面的模型,不管你给它起什么名字。)

  3. 您在 Html.EditorFor 的这些定义中看到的第一个参数并不是真正的参数。您会注意到他们使用this关键字来定义扩展方法。该参数指的是调用该方法的对象,在本例中是HtmlHelper<Model>对象。

于 2012-05-06T00:27:20.027 回答
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不是参数,它是类的类型,该函数扩展。

于 2012-05-06T00:29:02.273 回答
1

=>操作符视为“去”的意思,所以(m => m)意味着“m 去到 m”,另一种说法是你得到了同样的东西m

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

于 2012-05-06T00:28:28.750 回答