Получение сведений, хранящихся в атрибутах
Получение пользовательского атрибута — это простой процесс. Сначала объявите экземпляр атрибута, который требуется извлечь. Затем используйте метод Attribute.GetCustomAttribute, чтобы инициализировать новый атрибут значением того атрибута, который требуется извлечь. После инициализации нового атрибута можно использовать его свойства для получения значений.
Важный
В этой статье описывается, как получить атрибуты для кода, загруженного в контекст выполнения. Чтобы получить атрибуты для кода, загруженного в контекст только для отражения, необходимо использовать класс CustomAttributeData, как показано в разделе How to: Load Assemblies in the Reflection-Only Context.
В этом разделе описаны следующие способы получения атрибутов:
извлечение нескольких экземпляров атрибута, примененного к одной области
получение нескольких экземпляров атрибута, примененного к различным областям
Получение одного экземпляра атрибута
В следующем примере 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: {MyAttribute.Name}.");
// Get the Level value.
Console.WriteLine($"The Level Attribute is: {MyAttribute.Level}.");
// Get the Reviewed value.
Console.WriteLine($"The Reviewed Attribute is: {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
можно изменить, чтобы отобразить сведения, найденные в обоих атрибутах. Помните, что нужно применять несколько атрибутов на одном уровне. Атрибут должен быть определен со свойством AllowMultiple
, равным true
в классе AttributeUsageAttribute.
В следующем примере кода показано, как использовать метод 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: {MyAttributes[i].Name}.");
// Get the Level value.
Console.WriteLine($"The Level Attribute is: {MyAttributes[i].Level}.");
// Get the Reviewed value.
Console.WriteLine($"The Reviewed Attribute is: {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: {att.Name}.");
Console.WriteLine($"The Level Attribute on the class level is: {att.Level}.");
Console.WriteLine($"The Reviewed Attribute on the class level is: {att.Reviewed}.\n");
}
// 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: {attribute.Description}");
}
else
{
Console.WriteLine("Attribute not found.");
}
}
}