在学习ASP.NET MVC中,遇到了一个问题。@Html.ActionLink("linkText","actionName")
,这行代码的注释写的是HtmlHelper.ActionLink()
。这让我感到很奇怪,Html和HtmlHelper有什么关系?
于是,我开始搜索。发现,原来跟扩展方法有关,又涨姿势了。(老鸟误入,我是小白~)
扩展方法[1]
- 扩展方法,指为一个类提供可以扩展的方法。在不改变源代码的前提下,从外部提供一种可扩展的方法。
- 扩展方法构建的条件:类,以及类里添加方法。有三点需要注意:
(1)实现扩展方法的类必须是静态类,类的名称可以随意起;
(2)实现扩展的方法必须是静态方法;
(3)实现扩展的方法的第一个参数必须使用this关键字指明要实现扩展方法的类。
- 创建HtmlHelper类的扩展方法:
/// <summary>
/// 1.定义一个静态类,类名随便
/// </summary>
public static class MyHtmlHelperExt
{
/// <summary>
/// 2.实现一个具体的静态方法
/// </summary>
/// <param name="helper">3.第一个参数必须使用this关键字指定要使用扩展方法的类型</param>
/// <param name="value"></param>
/// <returns></returns>
public static HtmlString MyExtHtmlLabel(this HtmlHelper helper,string value)
{
return new HtmlString(string.Format("<span style='font-weight:bold;'>hello-{0}-end.</span>", value));
}
}
- 使用该扩展方法:
@Html.MyExtHtmlLabel("xxl")
如何判定@Html.ActionLink("linkText","actionName")
是HtmlHelper的扩展方法
这里推荐大家使用反编译工具:.NET Reflector。通过在反编译工具中查找ActionLink
可以发现如下图1所示:
通过图1可以看出,方法中第一个参数描述的是HtmlHelper
这个类,所以可以判定:ActionLink
是HtmlHelper
的扩展函数。
那么,又有一个问题来了。
为什么可以用Html来引用HtmlHelper类的扩展方法
我们应该找到.cshtml文件的程序集,利用反编译工具来查找它最终编译成的文件中具体的类与方法是如何构成的。
通过.cshtml文件定义的View能够被执行,必须先被编译成存在于某个程序集的类型,ASP.NET MVC采用动态编译的方式对View文件实施编译。当我们在对ASP.NET MVC进行部署的时候,需要对.cshtml文件进行打包。针对某个View的第一次访问会触发针对它的编译,一个View对应着一个类型。[2]
在默认情况下,View文件被动态编译后生成的程序集被临时存放在ASP.NET的临时目录“%WinDir%\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\”下。
从反编译工具中可以看到如图2所示:
从图2中可以看出,我们的cshtml编译后的类继承于WebViewPage类,那么:WebViewPage类是什么?看图3:
从图3可以看出,Html是WebViewPage类的一个属性,这个属性的类型就是HtmlHelper类。[3]
总结
- 所有的.cshtml类继承于WebViewPage类
- WebViewPage类中有一个
public HtmlHelper<TModel> Html
属性; - HtmlHelper类有很多扩展方法,包括ActionLink();
- 因此:所有的.cshtml文件中都可以使用Html.ActionLink()
自我反思
- 这个问题困扰了我好几天,各种查找资料,才理清了思路。这说明自己对于C#的掌握还是远远不够的,需要不断学习才对。
- 在一个类中(asp.net的web页面也最终会编译成类),突然出现的方法调用,首先想到的是:这个方法是不是父类中继承过来的?查找父类很重要
- 学习,记录,反思。写出来后,思路明显更清晰了。大家看到有谬误的地方欢迎指正。