了解 Func<T, TResult> 使用 MVC 委托

Understanding Func<T, TResult> Delegate with MVC

我正在努力思考 Func < T, TResult> Delegate,但似乎我不清楚。我知道 T 是一个参数 & TResult 是一个 return 类型。

在 MVC 中我一直使用这个函数:

@model Products
@Html.TextBoxFor(s=>s.my_property)

现在 TextBoxFor Function 如何知道传递给我的参数实际上是一个“Products 模型”。

下面是 TextBoxFor Model 的签名:

public static MvcHtmlString TextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    IDictionary<string, Object> htmlAttributes
)

所以我的问题是,当我调用 Html.TextBoxFor(s) 时,这个方法怎么知道 "s" 是一个 "Products" 模型以及 TModel 如何映射到参数 "s"(知道它的产品型号和我需要 return 东西)?

由于 @model Products 指令,Html 属性 (@Html) 的类型为 HtmlHelper<Products>。这就是 Razor 引擎的工作原理。

TextBoxForHtmlHelper<TModel> 的扩展方法,在您的代码中,您在 HtmlHelper<Products> 的实例上调用它,因此 TModel 被解析为Products.

然后,编译器可以轻松地将 TProperty 绑定到 my_property 的类型,因为它知道 TModel 是什么并且可以推断出 lambda 是什么"returns".


旁注:您必须知道 Expression<Func<T>> 完全 不同于 Func<T>:

  • Func<...>只是一个简单的委托,引用某处的一段可执行代码,即opaque.
  • 另一方面,
  • Expression<Func<...>> 是一个 表达式树 ,它是 AST.
  • 的一种

当您编写 lambda 时,编译器会根据您将 lambda 分配给 Func<...> 还是 Expression<Func<...>> 生成不同的代码。在第一种情况下,它将编译 lambda 并生成一个委托。在第二种情况下,它会发出一个表达式树。

如需更深入的解释,您可以阅读 Eric Lippert 的系列文章 Lambda 表达式与匿名方法Part 1, Part 2, Part 3, Part 4, Part 5