MVC扩展方法HtmlHelper方法签名语法

时间:2015-01-14 23:36:13

标签: c# asp.net-mvc extension-methods

我编写了以下代码来格式化C#MVC 5网站上的价格。再看一遍,我不知道它是如何工作的。

静态函数方法签名中“this”关键字的作用是什么?为什么我需要传递html参数,它没有在函数中使用?这甚至如何编译?

这个HtmlHelper html 是我觉得令人困惑的部分。以这种方式使用“this”关键字是否合法?

public static MvcHtmlString PrettyUSD(this HtmlHelper html, int amount)
        {
            if (amount == 0)
            {
                return MvcHtmlString.Create("N/A");
            }
            else
            {
                return MvcHtmlString.Create(string.Format("{0:C0}", amount));
            }
        }

2 个答案:

答案 0 :(得分:2)

这是extension method。扩展方法只是一种语法糖。 this关键字实际上将此方法标记为扩展方法。

来自文档:

  

扩展方法使您可以向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为扩展类型的实例方法。对于用C#和Visual Basic编写的客户端代码,调用扩展方法和实际在类型中定义的方法之间没有明显区别。

您可以这样调用您的方法:

html.PrettyUSD(42);

这完全等同于:

YourClassName.PrettyUSD(html, 42);

它可以让您编写相同的机制,例如:

new[] { 1, 4, 10, 42 }.Average();

Array类型没有Average方法,但System.Linq.Enumerable类有一个这样的定义(至少它是其重载之一):

public static double Average(this IEnumerable<int> source)

正如您所看到的,这可以让您定义一个方法,就像它在IEnumerable<int>接口上声明一样。

您的函数不使用HtmlHelper类,但它的使用使得它可以用于传统的ASP.NET MVC Razor方式:

The price is <strong>@Html.PrettyUSD(42)</strong>

答案 1 :(得分:2)

要回答“为什么我需要传递html参数,它在函数中没有使用?”......

在您的特定情况下,您不使用它,但它非常有用,因为它可以让您访问ViewBagViewData和许多其他属性。例如,这是一个扩展方法,用<br />替换换行符以格式化文本,它采用lambda表达式而不是直接值。

public static MvcHtmlString DisplayWithBreaksFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    var model = html.Encode(metadata.Model).Replace(Environment.NewLine, "<br />");

    if (String.IsNullOrEmpty(model))
        return MvcHtmlString.Empty;

    return MvcHtmlString.Create(model);
}

注意它是如何评估expressionhtml.ViewData以使模型属性格式化的。用法如下:

Html.DisplayWithBreaksFor(model => model.Description)