我编写了以下代码来格式化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));
}
}
答案 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参数,它在函数中没有使用?”......
在您的特定情况下,您不使用它,但它非常有用,因为它可以让您访问ViewBag
,ViewData
和许多其他属性。例如,这是一个扩展方法,用<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);
}
注意它是如何评估expression
对html.ViewData
以使模型属性格式化的。用法如下:
Html.DisplayWithBreaksFor(model => model.Description)