属性是.NET Framework最有用的的特性之一,研究它们需要花费大量时间,但是掌握了之后,对我们开发是非常有帮助的
讲之前,大家要知道.net framework属性和C#属性是有区别的哦,不要搞错了.
下面我们讲讲它的概念
.net framework属性是一个包含程序集中其他数据的类,这些数据涉及到程序集或程序集中的任何类型.
它的格式大家肯定也不陌生,在项目中的properties文件夹下有个AssemblyInfo.cs
Code
[assembly: AssemblyTitle("BugFix")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("BugFix")]
[assembly: AssemblyCopyright("Copyright @ Microsoft 2004")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
这些就是属性的基本格式了,即用方括号把属性括起来.assembly:标记定义了属性的作用域,其它代码声明了属性,就拿AssemblyTitle属性来说,它有一个构造函数,只有一个参数---字符串值.我们如果要访问这个值的话,可以通过Ildasm查看程序集,或通过"反射"编程访问该值.
说到"反射",也顺带提下吧,反射就是用编程的方式查看程序集,获得程序集的信息,这些信息包含所有对象的类型,用户添加到这些类型中的属性等.用到反射的话,我们要引入System.Reflection这个命名空间.
唠叨完属性的基础知识,就进入我们今天的正题--定制属性(就是创建自己的属性).
定制属性分为三个步骤
1.创建一个派生于System.Attribute的类
2.按照需要创建构造函数和公共属性
3.给类添加属性,以定义可以在什么地方使用定制属性
下面结合一个实例来讲
首先创建一个控制台应用程序,命名为BugFix
不要忘了引入两个重要的命名空间
using System;
using System.Reflection;
接着我们就开始创建自己的属性
Code
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Property |
AttributeTargets.Method |
AttributeTargets.Constructor,
AllowMultiple = true)]
public class BugFixAttribute : Attribute //定制一个BugFixAttribute属性类
{
public BugFixAttribute(string bugNumber, string comments)
{
BugNumber = bugNumber;
Comments = comments;
}
public readonly string BugNumber;
public readonly string Comments;
public string Author = null;
public override string ToString() //重写ToString()方法
{
if (null == Author)
return string.Format("BugFix {0} : {1}", BugNumber, Comments);
else
return string.Format("BugFix {0} by {1} : {2}", BugNumber, Author, Comments);
}
public static void DisplayFixes(System.Type t) //静态方法DisplayFix
{
object[] fixes = t.GetCustomAttributes(typeof(BugFixAttribute), false);//反射t中的BugFix属性
Console.WriteLine("Displaying fixes for {0}", t);
foreach (BugFixAttribute bugFix in fixes)
{
Console.WriteLine(" {0}", bugFix);
}
foreach (MemberInfo member in t.GetMembers(BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static)) //迭代类上的所有成员,并用BindingFlags枚举限制返回成员列表
{
object[] memberFixes = member.GetCustomAttributes(typeof(BugFixAttribute), false);
if (memberFixes.Length > 0) //如果Bugfix属性数目大于0
{
Console.WriteLine(" {0}", member.Name); //输出这些成员
foreach (BugFixAttribute memberFix in memberFixes)
{
Console.WriteLine(" {0}", memberFix);
}
}
}
}
}
我们先是创建了一个BugFixAttribute类,让它继承Attribute类,它的构造函数有两个参数,都是string类型的.为什么这样呢,暂时放一放,呆会下面会提到.然后我们重写了ToString方法,接着就是最重要的一块,用静态方法DisplayFixes()反射BugFix属性
ps:
AttributeUsage:用来定义属性用在什么地方.
AllowMultiple:定义用户是否能给元素添加一个或多个相同的属性
BindingFlags:一个枚举.这里是用来限制返回成员类型的
BugFix属性怎么用呢,可以按照如下方式
Code
[BugFix("101", "Created some methods")]
public class MyBuggyCode //MyBuggyCode类
{
[BugFix("90125", "Removed call to base()", Author = "Morgan")]
public MyBuggyCode()
{
}
[BugFix("2112", "Returned a non null string")]
[BugFix("38382", "Returned OK")]
public string DoSomething()
{
return "OK";
}
}
在第一段代码中,我们讲到BugFixAttribute的构造函数用两个参数,bugNumber即指一个错误号,就是上面的101,90125
而comments就是注释错误的信息.即"Create some methods","Removed call to base"等
我们创建DisplayFixes这个静态方法就是为了获取MyBuggyCode这个类的属性
最后通过调用DisplayFixes方法将获取的属性值输出
Code
public class BugRiddenCode
{
public static void Main() //入口函数,调用了DisplayFixes这个静态方法
{
BugFixAttribute.DisplayFixes(typeof(MyBuggyCode));
Console.ReadKey();
}
}
输出结果如下:
Code
Displaying fixes for MyBuggyCode
BugFix 101:Create some methods
DoSomething
BugFix 38382:Returned OK
BugFix 2112:Returned a non null string
.ctor
BugFix 90125 by Morgan:Removed call to base()
ps: .ctor是指的构造函数
通过BugFix这个小例子,相信大家对定制属性有所了解
后话:
高效的使用属性,可以做很多事情
可以定义程序集的信息,如版权信息啊
可以将代码块标记为过时,以修订程序集
创建自己的属性可以测试代码
我们还可以通过属性生成数据库表等等,虽然可能花费我们大量的时间去研究,但都是值得的,大家有好的例子,不要忘了发出来探讨一下