

























原文:Using Attribute In C#
绪论
属性是一种新的声明性信息.使用属性既可以定义设计级信息(例如一个帮助文件或一个文档链接)又可以定义运行时信息(例如使一个XML和一个类相关联).也可以使用属性创建"自描述"组件.通过此篇教程,我们将了解如何创建并附加属性到不同的程序实体,和在运行时如何找到属性信息.
定义
MSDN的描述是(ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm):"属性是附加说明的信息,既一个声明的详细说明".
使用预定义属性
在C#里有一小部分预定义属性.在学习如何创建我们自定义属性前,我们先看看如何在我们的代码里使用那些属性.
using System;
public class AnyClass
{
[Obsolete("Don't use Old method, use New method", true)]
static void Old( ) { }static void New( ) { }public static void Main( )
{
Old( );
}
}
using System;
public class HelpAttribute : Attribute
{
}
不管你是否相信,我们已经正确的创建了一个自定义属性.我们可以像使用Obsolete属性一样用上面的属性来装饰我们的类.
[Help()]
public class AnyClass
{
}
using System;
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
[Help(
让我们来实践下.我们将在Help属性类上使用AttrubuteUsage属性来控制Help属性类的用法.
using System;
[AttributeUsage(AttributeTargets.Class),
AllowMultiple = false, Inherited = false ]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
首先,看看AttributeTargets.Class.它规定Help属性只能用在类上.这意味着下面的代码将产生一个错误:
AnyClass.cs: Attribute 'Help' is not valid on this declaration type. It is valid on 'class' declarations only.
现在将它用在一个方法上.
Help("this is a do-nothing class")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
使用AttributeTargets.All可以允许Help属性应用在任何程序体上(可能值为: Assembly, Module, Class, Struct, Enum, Constructor, Method, Property, Field, Event, Interface, Parameter, Delegate, All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate, ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface)
现在看看AllowMultiple=false. 它规定属性不能多次使用在同一个程序体上.
[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
First Case
如果我们查找Derive类的Help属性,我们将找不到它的属性(attribute),因为inherited值为false.
Second Case
与上例没有什么不同, inherited值也为false.
Third Case
为了解释第3和第4个例子,让我们给Derive类添加和Base类相同的属性.
[Help("BaseClass")]
public class Base
{
}
[Help("DeriveClass")]
public class Derive : Base
{
}
如果我们现在查找Help属性,我们将仅得到Drive类的属性,因为继承属性值为true,但是不允许多重属性,所以基类的Help属性被Derive类的Help属性覆盖了.
Fourth Case
在第4个例子里,当我们查找Derive类的Help属性时将得到所有的属性,因为继承和多重属性是被允许的.
Note: AttributeUsage属性使用在继承自System.Attribute的类上才有效, AllowMultiple和Inherited默认都为false.
定位参数对命名参数
定位参数是属性构造函数的参数.它们是一种强制值,无论属性被置于何种程序实体,此参数都必须传递给构造函数.另方面,命名参数实际上使用的是可选的无参构造函数.
为了更详细的解释,让我们添加一些其他的属性(property)到Help属性类.
[AttributeUsage(AttributeTargets.Class,AllowMultiple = false,Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
this.version = "No Version is defined for this class";
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
protected String version;
public String Version
{
get
{
return this.version;
}
//if we ever want our attribute user to set this property,
//we must specify set method for it
set
{
this.version = value;
}
}
}
[Help("This is Class1")]
public class Class1
{
}
[Help(
"This is Class2", Version = "1.0")][Help(
"This is Class3", Version = "2.0",Description = "This is do-nothing class")][Help("This is Class2", Version = "1.0")]
在AttributeUsage例子里, ValidOn是定位参数, Inherited和AllowMultiple是命名参数.属性标志符
假如我们要将Help属性应用到整个程序集,出现的第一个问题是:我们需要确定Help属性放在哪里编译器才能识别这是应用在整个程序集上的?另一种情况:要将属性应用在一个有返回类型的方法上时.编译器如何识别这是应用在一个返回类型的方法上而不是所有的方法上?
我们使用属性标识符来解决这种模棱两可的问题.通过属性标识符,可以很明确地陈述要将属性应用于哪个实体.
例如:
[assembly: Help("this a do-nothing assembly")]
在Help属性之前的Assembly标志符明确的告诉编译器当前属性应用于整个程序集,可能的标志符是:using System;
using System.Reflection;
using System.Diagnostics;//attaching Help attribute to entire assembly
[assembly : Help("This Assembly demonstrates custom attributes creation and their run-time query.")]
//our custom attribute class
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
//
// TODO: Add constructor logic here
this.description = Description_in;
//
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
//attaching the Help attribute to our AnyClass
[HelpString("This is a do-nothing Class.")]
public class AnyClass
{
//attaching the Help attribute to our AnyMethod
[Help("This is a do-nothing Method.")]
public void AnyMethod()
{
}
//attaching Help attribute to our AnyInt Field
[Help("This is any Integer.")]
public int AnyInt;
}
class QueryApp
{
public static void Main()
{
}
}
class QueryApp
{
public static void Main()
{
HelpAttribute HelpAttr;//Querying Assembly Attributes
String assemblyName;
Process p = Process.GetCurrentProcess();
assemblyName = p.ProcessName + ".exe";
Assembly a
= Assembly.LoadFrom(assemblyName);foreach (Attribute attr in a.GetCustomAttributes(true))Type type = typeof(AnyClass);
使用typeof运算符获得AnyClass类的类型.其余的代码和前面的代码一样查找类里的属性,就不用再解释了.class QueryApp
{
public static void Main()
{
Type type = typeof(AnyClass);
HelpAttribute HelpAttr;
//Querying Class Attributes
foreach (Attribute attr in type.GetCustomAttributes(true))
{
HelpAttr = attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of AnyClass:\n{0}",HelpAttr.Description);
}
}
//Querying Class-Method Attributes
foreach(MethodInfo method in type.GetMethods())
{
foreach (Attribute attr in method.GetCustomAttributes(true))
{
HelpAttr = attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of {0}:\n{1}",method.Name, HelpAttr.Description);
}
}
}
//Querying Class-Field (only public) Attributes
foreach(FieldInfo field in type.GetFields())
{
foreach (Attribute attr in field.GetCustomAttributes(true))
{
HelpAttr= attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of {0}:\n{1}",field.Name,HelpAttr.Description);
}
}
}
}
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。