作者:浪子花梦,一个有趣的程序员 ~
此文章将讲解 .net 上面一个非常有用的技术 —— 定制特性,学习源于《CLR via C#》,菜鸟教程 . . .
文章目录
定制特性介绍与简单使用
我在以前的学习中就接触过了定制特性,当时只知道抄代码,根本不知道它是什么意思,在如下两篇文章中就有所遇到过:
1)C# 之 鼠标点击进程 —— 截取图片
2)C# 精通之路 —— 基本类型杂项详解(StringBuilder、枚举位标志、下限非0的数组),这些细节知识你知多少?
我们可以通过定制特性给我们现成的类添加额外的辅助,例如我上次在位标志相关文章中写过一个叫 [Flags]
的特性,这个特性重写了枚举中的 ToString方法,使它以字符串的形式输出数据,如下所示:
–
Obsolete 定制特性
下面我们来介绍一下一个叫 [Obsolete]
的特性,当我们想把一个类中的方法放弃,但又不想把它删除时,这个特性就派上用处了,Obsolete 定制特性有两个必需的定位参数:
下面的代码将演示这种特性的使用方式:
using System;
public class MyClass
{
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod()
{
Console.WriteLine("It is the old method");
}
static void NewMethod()
{
Console.WriteLine("It is the new method");
}
public static void Main()
{
OldMethod();
}
}
运行程序我们将发生下面这种情况:
这个方法已经过时了,并且显示我们自定义的消息:
Don’t use OldMethod, use NewMethod instead
当我们把第二个定位参数改为 false时,编译器将发出警告,但程序是可以编译通过的:
.NET Framework 为我们准备了大量的定制特性,有兴趣的小伙伴可以自己查看文档 . . .
.
.
.
自定义定制特性(示例讲解)
下面我们将通过一个示例来讲解一个定制特性是怎么写出来的 . . .
定制特性定义
定制的特性类需要从 Attribute 类派生,如下所示我们定义一个从 Attribute派生的类,这个类的里面有三个字段,分别是:sayHello,sayLoveyou,name,并且我们在构造器中对他们进行了初始化:
public class WelcomeInfoAttribute: System.Attribute
{
private String sayHello;
private String sayLoveyou;
private String name;
public WelcomeInfo(String name, String hello, String love)
{
this.name = name;
this.sayHello = hello;
this.sayLoveyou = love;
}
public String SayHello
{
get { return sayHello; }
}
public String SayLoveyou
{
get { return sayLoveyou; }
}
public String Name
{
get { return name; }
}
}
当前,我们不可能让定制特性去随意的使用,我们可以使用 [AttributeUsage]
去限制我们自己的自定义特性,让我们的特性只限制针对类,或者方法等等成员,也可以限制这个特性是否可以重复使用,或者在基类上面使用这个特性,派生类是否限制住不使用这个特性,原型如下所示:
现在我们来使用这个特性,用于限制我们的自定义定制特性,使用方法如下所示:
我们将这个特性应用在类或者方法中,并且可以重复使用,不允许有基类派生到子类中 . . .
.
定制特性使用
我们的定制特性准备好了,现在让我们来试试怎么用吧 . . .
我们定义一个People类,其中只有一个方法,特性使用如下所示:
我们在类和方法上面,分别使用了两次特性,特性的使用方法就是这么简单 . . .
.
定制特性访问 > 反射基础
我们现在需要做的,就是通过这个 People类 来访问到我们自己的定制特性中的信息 . . .
要想访问的话,我们先来看一下 CustomAttributeExtensions 这个类,这个类中定义了三个方法,这三个方法又有许多种重载的版本,如下所示:
1)GetCustomAttribute:
2)GetCustomAttributes:
3)IsDefined:
我们这个示例只用到了 GetCustomAttributes 方法,即获取当前此类型中的所有特性类,主函数测试代码如下所示:
public static void Main()
{
People people = new People();
people.SayHello();
Type type = people.GetType();
foreach (var p in type.GetCustomAttributes(false))
{
WelcomeInfo welcome = (WelcomeInfo)p;
if (welcome != null) // 此特性应用在类上
{
Console.WriteLine("Name: " + welcome.Name);
Console.WriteLine("SayHello: " + welcome.SayHello);
Console.WriteLine("SayLoveyou: " + welcome.SayLoveyou);
Console.WriteLine();
}
}
Console.WriteLine();
Console.WriteLine();
foreach (var p in type.GetMethods()) // 获取这个类的所有方法,这个类只有一个方法
{
foreach (var item in p.GetCustomAttributes(false))
{
WelcomeInfo welcome;
try { welcome = (WelcomeInfo)item; }
catch { break; }
if (welcome != null) // 此特性应用在方法上面
{
Console.WriteLine("Name: " + welcome.Name);
Console.WriteLine("SayHello: " + welcome.SayHello);
Console.WriteLine("SayLoveyou: " + welcome.SayLoveyou);
Console.WriteLine();
}
}
}
Console.ReadKey();
}
输出的结果如下所示:
.
.
.