属性与程序元素关联后,反射可用于查询其存在和值。 .NET 提供了 MetadataLoadContext可用于检查无法加载执行的代码。
MetadataLoadContext
无法执行加载到上下文中的 MetadataLoadContext 代码。 这意味着无法创建自定义属性的实例,因为这需要执行其构造函数。 若要在上下文中 MetadataLoadContext 加载和检查自定义属性,请使用类 CustomAttributeData 。 可以使用静态 CustomAttributeData.GetCustomAttributes 方法的相应重载来获取此类的实例。 有关详细信息,请参阅 如何:使用 MetadataLoadContext 检查程序集内容。
执行上下文
用于查询执行上下文 MemberInfo.GetCustomAttributes 中的属性的主要反射方法是 MemberInfo.GetCustomAttributes 和 。
自定义属性的可访问性是相对于其所附的程序集进行检查的。 这相当于检查程序集中附加有自定义属性的类型中的某方法是否可以调用该自定义属性的构造函数。
方法如 Assembly.GetCustomAttributes(Boolean) 检查类型参数的可见性和可访问性。 只有在包含用户定义类型的程序集中的代码可以使用 GetCustomAttributes
来获取该类型的自定义属性。
以下 C# 示例是典型的自定义属性设计模式。 它说明了运行时自定义属性反射模型。
System.DLL
public class DescriptionAttribute : Attribute
{
}
System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}
public class LocalizationExtenderProvider
{
[MyDescriptionAttribute(...)]
public CultureInfo GetLanguage(...)
{
}
}
如果运行时尝试检索附加到DescriptionAttribute方法的GetLanguage
公共自定义属性类型的自定义属性,它将执行以下操作:
- 运行时检查类型参数
DescriptionAttribute
给Type.GetCustomAttributes(Type type)
是公开的,因此是可见且可访问的。 - 运行时检查派生自
MyDescriptionAttribute
的用户定义类型DescriptionAttribute
在 System.Web.dll 程序集中是否可见且可访问,以及该类型在其附加到方法GetLanguage()
的位置。 - 运行时检查 System.Web.dll 程序集中的构造函数
MyDescriptionAttribute
是否可见且可访问。 - 运行时使用自定义属性参数调用构造函数
MyDescriptionAttribute
,并将新对象返回到调用方。
自定义属性反射模型可能会将用户定义类型的实例泄漏到定义该类型的程序集之外。 这与运行时系统库中返回用户定义类型的实例(例如 Type.GetMethods 返回对象数组 RuntimeMethodInfo
)的成员没有区别。 为了防止客户端发现关于用户定义的自定义属性类型的信息,请将这些类型的成员定义为非公共。
以下示例演示了使用反射获取自定义属性访问权限的基本方法。
using System;
public class ExampleAttribute : Attribute
{
private string stringVal;
public ExampleAttribute()
{
stringVal = "This is the default string.";
}
public string StringValue
{
get { return stringVal; }
set { stringVal = value; }
}
}
[Example(StringValue="This is a string.")]
class Class1
{
public static void Main()
{
System.Reflection.MemberInfo info = typeof(Class1);
foreach (object attrib in info.GetCustomAttributes(true))
{
Console.WriteLine(attrib);
}
}
}
Public Class ExampleAttribute
Inherits Attribute
Private stringVal As String
Public Sub New()
stringVal = "This is the default string."
End Sub
Public Property StringValue() As String
Get
Return stringVal
End Get
Set(Value As String)
stringVal = Value
End Set
End Property
End Class
<Example(StringValue:="This is a string.")> _
Class Class1
Public Shared Sub Main()
Dim info As System.Reflection.MemberInfo = GetType(Class1)
For Each attrib As Object In info.GetCustomAttributes(true)
Console.WriteLine(attrib)
Next attrib
End Sub
End Class