检索存储在属性中的信息
检索自定义属性是一个简单的过程。 首先,声明要检索的属性的实例。 然后,使用 Attribute.GetCustomAttribute 方法将新属性初始化为要检索的属性的值。 初始化新属性后,可以使用其属性获取值。
重要
本文介绍如何检索加载到执行上下文中的代码的属性。 若要为仅反射上下文中加载的代码检索属性,必须使用 CustomAttributeData 类,如如何:将程序集加载到仅反射上下文中所述。
本部分介绍检索属性的以下方法:
检索属性 的单个实例
检索应用于同一作用域 的属性的多个实例
检索属性的单个实例
在下面的示例中,DeveloperAttribute
(如上一部分所述)在类一级适用于 MainApp
类。 GetAttribute
方法使用 GetCustomAttribute
检索类级别上 DeveloperAttribute
中存储的值,然后再将其显示到控制台。
using namespace System;
using namespace System::Reflection;
using namespace CustomCodeAttributes;
[Developer("Joan Smith", "42", Reviewed = true)]
ref class MainApp
{
public:
static void Main()
{
// Call function to get and display the attribute.
GetAttribute(MainApp::typeid);
}
static void GetAttribute(Type^ t)
{
// Get instance of the attribute.
DeveloperAttribute^ MyAttribute =
(DeveloperAttribute^) Attribute::GetCustomAttribute(t, DeveloperAttribute::typeid);
if (MyAttribute == nullptr)
{
Console::WriteLine("The attribute was not found.");
}
else
{
// Get the Name value.
Console::WriteLine("The Name Attribute is: {0}." , MyAttribute->Name);
// Get the Level value.
Console::WriteLine("The Level Attribute is: {0}." , MyAttribute->Level);
// Get the Reviewed value.
Console::WriteLine("The Reviewed Attribute is: {0}." , MyAttribute->Reviewed);
}
}
};
using System;
using System.Reflection;
using CustomCodeAttributes;
[Developer("Joan Smith", "42", Reviewed = true)]
class MainApp
{
public static void Main()
{
// Call function to get and display the attribute.
GetAttribute(typeof(MainApp));
}
public static void GetAttribute(Type t)
{
// Get instance of the attribute.
DeveloperAttribute MyAttribute =
(DeveloperAttribute) Attribute.GetCustomAttribute(t, typeof (DeveloperAttribute));
if (MyAttribute == null)
{
Console.WriteLine("The attribute was not found.");
}
else
{
// Get the Name value.
Console.WriteLine("The Name Attribute is: {0}." , MyAttribute.Name);
// Get the Level value.
Console.WriteLine("The Level Attribute is: {0}." , MyAttribute.Level);
// Get the Reviewed value.
Console.WriteLine("The Reviewed Attribute is: {0}." , MyAttribute.Reviewed);
}
}
}
Imports System.Reflection
Imports CustomCodeAttributes
<Developer("Joan Smith", "42", Reviewed:=True)>
Class MainApp
Public Shared Sub Main()
' Call function to get and display the attribute.
GetAttribute(GetType(MainApp))
End Sub
Public Shared Sub GetAttribute(t As Type)
' Get instance of the attribute.
Dim MyAttribute As DeveloperAttribute =
CType(Attribute.GetCustomAttribute(t, GetType(DeveloperAttribute)), DeveloperAttribute)
If MyAttribute Is Nothing Then
Console.WriteLine("The attribute was not found.")
Else
' Get the Name value.
Console.WriteLine("The Name Attribute is: {0}.", MyAttribute.Name)
' Get the Level value.
Console.WriteLine("The Level Attribute is: {0}.", MyAttribute.Level)
' Get the Reviewed value.
Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute.Reviewed)
End If
End Sub
End Class
上述程序的执行显示以下文本:
The Name Attribute is: Joan Smith.
The Level Attribute is: 42.
The Reviewed Attribute is: True.
如果未找到该属性,GetCustomAttribute
方法将 MyAttribute
初始化为 null 值。 此示例检查 MyAttribute
此类实例,并在找不到该属性时通知用户。 如果在类范围中找不到 DeveloperAttribute
,控制台将显示以下消息:
The attribute was not found.
前面的示例假定属性定义位于当前命名空间中。 请记住导入属性定义所在的命名空间(如果它不在当前命名空间中)。
检索应用于同一作用域的属性的多个实例
在前面的示例中,要检查的类和要查找的特定属性将传递给 GetCustomAttribute 方法。 如果类级别上仅应用了一个属性的一个实例,则此代码有效。 但是,如果在同一类级别应用了属性的多个实例,则 GetCustomAttribute
方法不会检索所有信息。 如果同一属性的多个实例应用于同一范围,可以使用 Attribute.GetCustomAttributes 方法将所有属性实例放入数组中。 例如,如果在同一类的类级别应用了两个 DeveloperAttribute
实例,则可以修改 GetAttribute
方法以显示这两个属性中找到的信息。 请记住,在同一级别应用多个属性。 属性必须在 AttributeUsageAttribute 类中定义,其 AllowMultiple
属性设置为 true
。
下面的代码示例演示如何使用 GetCustomAttributes
方法创建一个数组,该数组引用任何给定类中的所有 DeveloperAttribute
实例。 然后,代码会将所有属性的值输出到控制台。
public:
static void GetAttribute(Type^ t)
{
array<DeveloperAttribute^>^ MyAttributes =
(array<DeveloperAttribute^>^) Attribute::GetCustomAttributes(t, DeveloperAttribute::typeid);
if (MyAttributes->Length == 0)
{
Console::WriteLine("The attribute was not found.");
}
else
{
for (int i = 0 ; i < MyAttributes->Length; i++)
{
// Get the Name value.
Console::WriteLine("The Name Attribute is: {0}." , MyAttributes[i]->Name);
// Get the Level value.
Console::WriteLine("The Level Attribute is: {0}." , MyAttributes[i]->Level);
// Get the Reviewed value.
Console::WriteLine("The Reviewed Attribute is: {0}.", MyAttributes[i]->Reviewed);
}
}
}
public static void GetAttribute(Type t)
{
DeveloperAttribute[] MyAttributes =
(DeveloperAttribute[]) Attribute.GetCustomAttributes(t, typeof (DeveloperAttribute));
if (MyAttributes.Length == 0)
{
Console.WriteLine("The attribute was not found.");
}
else
{
for (int i = 0 ; i < MyAttributes.Length ; i++)
{
// Get the Name value.
Console.WriteLine("The Name Attribute is: {0}." , MyAttributes[i].Name);
// Get the Level value.
Console.WriteLine("The Level Attribute is: {0}." , MyAttributes[i].Level);
// Get the Reviewed value.
Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttributes[i].Reviewed);
}
}
}
Public Shared Sub GetAttribute(t As Type)
Dim MyAttributes() As DeveloperAttribute =
CType(Attribute.GetCustomAttributes(t, GetType(DeveloperAttribute)), DeveloperAttribute())
If MyAttributes.Length = 0 Then
Console.WriteLine("The attribute was not found.")
Else
For i As Integer = 0 To MyAttributes.Length - 1
' Get the Name value.
Console.WriteLine("The Name Attribute is: {0}.", MyAttributes(i).Name)
' Get the Level value.
Console.WriteLine("The Level Attribute is: {0}.", MyAttributes(i).Level)
' Get the Reviewed value.
Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttributes(i).Reviewed)
Next i
End If
End Sub
如果未找到任何属性,此代码会向用户发出警报。 如果找到,就会显示两个 DeveloperAttribute
实例中包含的信息。
检索应用于不同作用域的属性的多个实例
GetCustomAttributes 和 GetCustomAttribute 方法不会搜索整个类并返回该类中属性的所有实例。 相反,它们一次只搜索一个指定的方法或成员。 如果你有一个类,其中相同的属性应用于每个成员,并且你想要检索应用于那些成员的所有属性中的值,那么必须单独将每个方法或成员提供给 GetCustomAttributes
和 GetCustomAttribute
。
下面的代码示例将一个类用作参数,并在类级别以及该类的每一个方法上搜索 DeveloperAttribute
(如前面所定义):
public:
static void GetAttribute(Type^ t)
{
DeveloperAttribute^ att;
// Get the class-level attributes.
// Put the instance of the attribute on the class level in the att object.
att = (DeveloperAttribute^) Attribute::GetCustomAttribute (t, DeveloperAttribute::typeid);
if (att == nullptr)
{
Console::WriteLine("No attribute in class {0}.\n", t->ToString());
}
else
{
Console::WriteLine("The Name Attribute on the class level is: {0}.", att->Name);
Console::WriteLine("The Level Attribute on the class level is: {0}.", att->Level);
Console::WriteLine("The Reviewed Attribute on the class level is: {0}.\n", att->Reviewed);
}
// Get the method-level attributes.
// Get all methods in this class, and put them
// in an array of System.Reflection.MemberInfo objects.
array<MemberInfo^>^ MyMemberInfo = t->GetMethods();
// Loop through all methods in this class that are in the
// MyMemberInfo array.
for (int i = 0; i < MyMemberInfo->Length; i++)
{
att = (DeveloperAttribute^) Attribute::GetCustomAttribute(MyMemberInfo[i], DeveloperAttribute::typeid);
if (att == nullptr)
{
Console::WriteLine("No attribute in member function {0}.\n" , MyMemberInfo[i]->ToString());
}
else
{
Console::WriteLine("The Name Attribute for the {0} member is: {1}.",
MyMemberInfo[i]->ToString(), att->Name);
Console::WriteLine("The Level Attribute for the {0} member is: {1}.",
MyMemberInfo[i]->ToString(), att->Level);
Console::WriteLine("The Reviewed Attribute for the {0} member is: {1}.\n",
MyMemberInfo[i]->ToString(), att->Reviewed);
}
}
}
public static void GetAttribute(Type t)
{
DeveloperAttribute att;
// Get the class-level attributes.
// Put the instance of the attribute on the class level in the att object.
att = (DeveloperAttribute) Attribute.GetCustomAttribute (t, typeof (DeveloperAttribute));
if (att == null)
{
Console.WriteLine("No attribute in class {0}.\n", t.ToString());
}
else
{
Console.WriteLine("The Name Attribute on the class level is: {0}.", att.Name);
Console.WriteLine("The Level Attribute on the class level is: {0}.", att.Level);
Console.WriteLine("The Reviewed Attribute on the class level is: {0}.\n", att.Reviewed);
}
// Get the method-level attributes.
// Get all methods in this class, and put them
// in an array of System.Reflection.MemberInfo objects.
MemberInfo[] MyMemberInfo = t.GetMethods();
// Loop through all methods in this class that are in the
// MyMemberInfo array.
for (int i = 0; i < MyMemberInfo.Length; i++)
{
att = (DeveloperAttribute) Attribute.GetCustomAttribute(MyMemberInfo[i], typeof (DeveloperAttribute));
if (att == null)
{
Console.WriteLine("No attribute in member function {0}.\n" , MyMemberInfo[i].ToString());
}
else
{
Console.WriteLine("The Name Attribute for the {0} member is: {1}.",
MyMemberInfo[i].ToString(), att.Name);
Console.WriteLine("The Level Attribute for the {0} member is: {1}.",
MyMemberInfo[i].ToString(), att.Level);
Console.WriteLine("The Reviewed Attribute for the {0} member is: {1}.\n",
MyMemberInfo[i].ToString(), att.Reviewed);
}
}
}
Public Shared Sub GetAttribute(t As Type)
Dim att As DeveloperAttribute
' Get the class-level attributes.
' Put the instance of the attribute on the class level in the att object.
att = CType(Attribute.GetCustomAttribute(t, GetType(DeveloperAttribute)), DeveloperAttribute)
If att Is Nothing
Console.WriteLine("No attribute in class {0}.\n", t.ToString())
Else
Console.WriteLine("The Name Attribute on the class level is: {0}.", att.Name)
Console.WriteLine("The Level Attribute on the class level is: {0}.", att.Level)
Console.WriteLine("The Reviewed Attribute on the class level is: {0}.\n", att.Reviewed)
End If
' Get the method-level attributes.
' Get all methods in this class, and put them
' in an array of System.Reflection.MemberInfo objects.
Dim MyMemberInfo() As MemberInfo = t.GetMethods()
' Loop through all methods in this class that are in the
' MyMemberInfo array.
For i As Integer = 0 To MyMemberInfo.Length - 1
att = CType(Attribute.GetCustomAttribute(MyMemberInfo(i), _
GetType(DeveloperAttribute)), DeveloperAttribute)
If att Is Nothing Then
Console.WriteLine("No attribute in member function {0}.\n", MyMemberInfo(i).ToString())
Else
Console.WriteLine("The Name Attribute for the {0} member is: {1}.",
MyMemberInfo(i).ToString(), att.Name)
Console.WriteLine("The Level Attribute for the {0} member is: {1}.",
MyMemberInfo(i).ToString(), att.Level)
Console.WriteLine("The Reviewed Attribute for the {0} member is: {1}.\n",
MyMemberInfo(i).ToString(), att.Reviewed)
End If
Next
End Sub
如果未在方法级别或类级别找到 DeveloperAttribute
实例,GetAttribute
方法会通知用户找不到任何属性,并显示不包含该属性的方法或类的名称。 如果找到属性,控制台将显示 Name
、Level
和 Reviewed
字段。
可以使用 Type 类的成员,在传递的类中获取各个方法和成员。 此示例首先查询 Type
对象以获取类级别的属性信息。 接下来,它使用 Type.GetMethods 将所有方法的实例放入 System.Reflection.MemberInfo 对象的数组中,以检索方法级别的属性信息。 你还可以使用 Type.GetProperties 方法来检查属性级别的特性,或使用 Type.GetConstructors 方法检查构造函数级别的特性。
从类成员检索属性
除了在类级别检索属性外,还可以将属性应用于各个成员,例如方法、属性和字段。 GetCustomAttribute
和 GetCustomAttributes
方法可用于检索这些属性。
例
以下示例演示如何检索应用于方法的属性:
using System;
using System.Reflection;
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
public string Description { get; }
public MyAttribute(string description) { Description = description; }
}
public class MyClass
{
[MyAttribute("This is a sample method.")]
public void MyMethod() { }
}
class AttributeRetrieval
{
public static void Main()
{
// Create an instance of MyClass
MyClass myClass = new MyClass();
// Retrieve the method information for MyMethod
MethodInfo methodInfo = typeof(MyClass).GetMethod("MyMethod");
MyAttribute attribute = (MyAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(MyAttribute));
if (attribute != null)
{
// Print the description of the method attribute
Console.WriteLine("Method Attribute: {0}", attribute.Description);
}
else
{
Console.WriteLine("Attribute not found.");
}
}
}