在未使用.net编写程序之前,如果想看自己写的一些函数的备注,就必须要找到该函数才可以看的到,利用.net里的属性和反射机制,可以很轻松的定制自己的属性,在自己的程序里使用自己定制的属性,而且可以利用反射把这些属性单独抽出来管理,这样就可以更轻松的管理我们的程序。以下的例子是我参考《C#高级编程》里的例子写的,觉得这个例子很有代表性,拿出来与大家共享,也算是抛砖引玉吧。
这个例子分三部分组成:第一部分是定制自己的属性;第二部分是在程序里使用自己定制的属性;第三部分是利用反射把程序里的属性单独抽出来。
我们如果要定义自己的属性,就得继承类Attribute,命名空间是System。还有一点需要说明的是我们在定制自己的属性时,必须说明该属性的用途,这样编译器才知道这些属性可以用在哪些地方,所以一般在属性类之前都有这样类似的代码,如下:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property,AllowMultiple = true,
Inherited = false)]
AttributeUsage是一个类,有关它的详细用法可以参考sdk帮助文档。
下面我们就开始定制自己的属性,如下:(可以把它编译成dll文件,以备其他的程序使用)
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property,AllowMultiple = true,
Inherited = false)]
public class LastModified : Attribute
{
private DateTime _lastModified;
private string _comment;
private string _issues;
public LastModified(string datetime,string comment)
{
this._lastModified = Convert.ToDateTime(datetime);
this._comment = comment;
}
//说明
public string Issues
{
get
{
return _issues;
}
set
{
_issues = value;
}
}
//备注
public string Comment
{
get
{
return _comment;
}
}
//修改日期
public DateTime Lastmodified
{
get
{
return _lastModified;
}
}
}
下面是在自己的程序中使用自己定义的属性,记得添加自己定义属性的引用,以下是我写的一个类Account,在它的一个方法里我用到了我自己定义的属性,如下:
[LastModified(" 2005/04/06","jah programed first")]
public void OutputAccount(int output)
{
if(output < 0)
{
myArgs.Balance = output;
Underzero(myArgs);
}
else if(output > balance)
{
myArgs.Balance = output;
Overspend(myArgs);
}
else
{
this.balance -= output;
}
}
下面我们就利用反射来把自己的属性抽取出来,在此为了快速的知道自己的程序是否支持自定义属性,我们可以在定义一个属性类,用它来检测是否支持自定义属性。代码如下:
[AttributeUsage(AttributeTargets.All,AllowMultiple = true,
Inherited = false)]
public class SupportNew : Attribute
{
}
这样我们就可以在Account类前面添加一行代码,说明它支持自定义属性,这样可以提高查找自定义属性的速度,代码为:[assembly:SupportNew],下面我就把第三部分的代码贴出来,如下:(记住引用上面编写好的自定义属性dll文件)为此我专门写了个类,它的功能是给定一个程序集,它就会查找所有的自定义属性,并把信息添加到一个ArrayList中。
using System;
using System.Collections;
using CustomAttribute;
using System.Reflection;
namespace LookUpAttribute
{
/// <summary>
/// 对于自定义的属性进行查询
/// </summary>
public class LookUp
{
private string _path;
private ArrayList _list;
public LookUp(string path)
{
_path = path;
_list = new ArrayList();
}
/// <summary>
/// 得到信息列表
/// </summary>
public ArrayList List
{
get
{
return _list;
}
}
/// <summary>
/// 对于给定的程序集进行处理,以便得到自定义属性
/// </summary>
public void DisplayAttribute()
{
//导入程序集
Assembly myAssembly = Assembly.LoadFrom(_path);
//看是否支持自定义属性
Attribute supportAttribute = Attribute.GetCustomAttribute(myAssembly,typeof(SupportNew));
string name = myAssembly.FullName;
this.AddToMessage(name);
if(supportAttribute == null)
{
this.AddToMessage("该程序集不支持SupportNewAttribute");
return;
}
else
{
this.AddToMessage("已经定义的类型如下:");
}
//得到程序集的所有的类型
Type[] myTypes = myAssembly.GetTypes();
foreach(Type myType in myTypes)
{
this.DisplayTypeInfo(myAssembly,myType);
}
}
/// <summary>
/// 把信息添加到ArrayList中
/// </summary>
/// <param name="msg">信息</param>
private void AddToMessage(string msg)
{
_list.Add(msg);
}
private void WriteAttributeInfo(Attribute attribute)
{
LastModified last = attribute as LastModified;
if(last == null)
return;
this.AddToMessage("时间:"+last.Lastmodified.ToShortDateString() + " 说明:" +last.Comment );
}
private void DisplayTypeInfo(Assembly assembly,Type type)
{
//不是类则不处理
if(!type.IsClass)
return;
this.AddToMessage("*************");
this.AddToMessage("类名:"+type.Name);
//类的自定义属性
Attribute[] attributes = Attribute.GetCustomAttributes(type);
if(attributes.Length == 0)
{
this.AddToMessage("该类本身没有自定义属性");
}
else
{
foreach(Attribute a in attributes)
{
this.WriteAttributeInfo(a);
}
}
BindingFlags flag = (BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
MethodInfo[] methods = type.GetMethods(flag);
//方法的自定义属性
foreach(MethodInfo nextMethod in methods)
{
Object[] obj = nextMethod.GetCustomAttributes(typeof(LastModified),false);
if(obj.Length > 0)
{
this.AddToMessage(type.Name+":"+nextMethod.Name);
foreach(Attribute a in obj)
{
this.WriteAttributeInfo(a);
}
}
}
}
}
}
最后我演练一下如何使用这个类,如下:
LookUp objLookup = new LookUp(this.txtPath.Text);
objLookup.DisplayAttribute();
ArrayList array = objLookup.List;
foreach(string msg in array)
{
this.lbResult.Items.Add(msg);
}
txtPath为一个文本框控件,lbResult为一个列表框控件,到此我们就可以察看我们的自定义属性了,这样管理起你自己的代码是不是方便多了,这样你就不用打开程序,只需要把程序集给它,你就可以知道哪一个函数的更新时间,或者是谁写的,其实属性的用途非常的广,具体的就要看你的思路了。
最后我要说的是,我是看了《C#高级编程》后写出来的,所以有很多代码是借鉴这本书的,所以如果你有什么疑惑的话,你可以看一下这本很不错的书。