访问自定义属性
更新:2007 年 11 月
当属性与程序元素相关联后,可以使用反射来查询它们是否存在以及它们的值。在 .NET Framework 1.0 和 1.1 版中,是在执行上下文中检查自定义属性。.NET Framework 2.0 版提供了新的加载上下文(只反射上下文),该上下文可用于检查无法加载执行的代码。
只反射上下文
加载到只反射上下文中的代码无法执行。这意味着不能创建自定义属性的实例,因为这将需要执行其构造函数。若要在只反射上下文中加载和检查自定义属性,请使用 CustomAttributeData 类。可以通过使用静态 CustomAttributeData.GetCustomAttributes 方法的相应重载获取此类的实例。请参见如何:将程序集加载到仅反射上下文中。
执行上下文
用于查询执行上下文中的属性的主要反射方法是 System.Reflection.MemberInfo.GetCustomAttributes 和 System.Reflection.Assembly.GetCustomAttributes。
自定义属性的可访问性根据附加该属性的程序集来进行检查。这相当于检查附加自定义属性的程序集中的类型上的方法是否可以调用自定义属性的构造函数。
诸如 System.Reflection.Assembly.GetCustomAttributes(Type, Boolean) 等方法检查类型参数的可见性和可访问性。只有包含用户定义类型的程序集中的代码才能使用 GetCustomAttributes 检索该类型的自定义属性。
下面的 C# 示例是典型的自定义属性设计模式。它说明运行库自定义属性反射模型。
System.DLL
public class DescriptionAttribute : Attribute
{
}
System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}
public class LocalizationExtenderProvider
{
[MyDescriptionAttribute(...)]
public CultureInfo GetLanguage(...)
{
}
}
如果运行库试图为附加到 GetLanguage 方法的公共自定义属性类型 DescriptionAttribute 检索自定义属性,则该运行库将执行下列操作:
运行库检查 Type.GetCustomAttributes(Type type) 的 DescriptionAttribute 类型参数是否为公共的,从而是否可见和访问。
运行库检查从 DescriptionAttribute 派生的用户定义类型 MyDescriptionAttribute 在 System.Web.DLL 程序集(它在该程序集中附加到 GetLanguage() 方法)内是否可见和可以访问。
运行库检查 MyDescriptionAttribute 的构造函数是否在 System.Web.DLL 程序集中可见和可以访问。
运行库调用带有自定义属性参数的 MyDescriptionAttribute 的构造函数,然后将新对象返回给调用方。
自定义属性反射模型可能会在定义类型的程序集外泄漏用户定义类型的实例。这与运行库系统库中返回用户定义类型的实例的成员(例如返回 RuntimeMethodInfo 对象数组的 Type.GetMethods())相同。为了防止客户端发现关于用户定义的自定义属性类型的信息,请将该类型的成员定义为非公共成员。
下面的示例说明使用反射访问自定义属性的基本方法。
Class Class1
Public Shared Sub Main()
Dim info As System.Reflection.MemberInfo = GetType(Class1)
Dim attributes() As Object = info.GetCustomAttributes(True)
For i As Integer = 0 To attributes.Length - 1
System.Console.WriteLine(attributes(i))
Next i
End Sub
End Class
class MyClass
{
public static void Main()
{
System.Reflection.MemberInfo info = typeof(MyClass);
object[] attributes = info.GetCustomAttributes(true);
for (int i = 0; i < attributes.Length; i++)
{
System.Console.WriteLine(attributes[i]);
}
}
}