扩展方法

在c#编程时,当我们需要给一个类增加方法,但又不希望修改这些类,也不希望创建这些类的子类,可以采用扩展方法。扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。我们用一个简单的例子说明方法扩展。

假设我们有一个Person类在程序集DomainEntry中,用于描述人的基本信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;

namespace ZL.DomainEntry
{
public class Person
{
public string Name { get; set; }

public DateTime BirthDay { get; set; }

public Person(string name,int year,int month,int day)
{
Name = name;
BirthDay = new DateTime(year, month, day);
}

}
}

我们希望给这个类增加一个方法GetAge,获取人的年龄。我们不希望修改Person类,这时就可以采用扩展方法来实现。我们新建一个项目,名称为ExtenMethods,然后可以创建扩展方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using ZL.DomainEntry;
using System;

namespace ZL.ExternMethods
{
//必须为静态类
public static class ExternPerson
{
/// <summary>
/// 扩展方法必须为静态方法
/// </summary>
/// <param name="person">这个参数必须有this修饰符,说明需要为Person扩展方法</param>
/// <returns>返回是整型</returns>
public static int GetAge(this Person person)
{
var age = DateTime.Now.Year - person.BirthDay.Year;

if(DateTime.Now.Month < person.BirthDay.Month)
{
age -= 1;
}

return age;
}
}
}

扩展方法需要注意下面几点:

  • 扩展方法的类必须是静态类
  • 扩展方法必须是静态方法
  • 扩展方法的第一个参数是用this修饰符加上需要扩展的类型名称

扩展方法在使用时与一般方法是一样的,只要使用using将扩展方法所在的名称空间导入,就可以使用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using ZL.DomainEntry;
using ZL.ExternMethods;
using System;

namespace ExternsionMethodDemo
{
class Program
{
static void Main(string[] args)
{
Person person = new Person("John", 2008, 11, 11);
Console.WriteLine(person.Name +"的生日:"+person.BirthDay.ToShortDateString() +",今年"+person.GetAge()+"岁");
Console.ReadLine();
}
}
}

使用扩展方法对类型进行扩充时,需要注意以下几点:

  • 扩展方法只能访问类型的public属性和方法,不能访问private和protected属性和方法。
  • 如果扩展方法的类型发生改变,扩展方法有可能失效。
  • 如果扩展方法的名称与类型中的方法具有相同的签名,扩展方法就不会被调用。

使用实例

在Asp.Net MVC编程时,我们可以使用扩展方法给HtmlHelper增加自定义的方法,在Razor模板中可以使用这些自定义的方法简化模板代码,并提高可读性。

比如:

1
2
3
4
5
6
7
8
9
10
11
public static class HtmlExtensions
{
public static MvcHtmlString Template(this HtmlHelper htmlHelper, object item)
{
return MvcHtmlString.Create(
HttpUtility.JavaScriptStringEncode(
htmlHelper.Action("index", "templates", item).ToHtmlString()
)
);
}
}

在模板中调用:

1
2
3
<script type="text/javascript">
var someJsTemplate = '@Html.Template(new { something = "abc" })';
</script>