특성에 저장된 정보 검색
사용자 지정 특성은 간단하게 검색할 수 있습니다. 먼저 검색할 특성의 인스턴스를 선언합니다. 그런 다음 Attribute.GetCustomAttribute 메서드를 사용하여 검색하려는 특성의 값으로 새로운 특성을 초기화합니다. 새로운 특성을 초기화한 다음에는 해당 속성을 사용하여 값을 가져오기만 하면 됩니다.
중요 |
---|
이 항목에서는 실행 컨텍스트에 로드된 코드의 특성을 검색하는 방법을 설명합니다.리플렉션 전용 컨텍스트에 로드된 코드의 특성을 검색하려면 방법: 리플렉션 전용 컨텍스트에 어셈블리 로드에서 볼 수 있듯이 CustomAttributeData 클래스를 사용해야 합니다. |
이 단원에서는 다음과 같은 특성 검색 방법을 설명합니다.
특성의 단일 인스턴스 검색
동일한 범위에 적용된 특성의 여러 인스턴스 검색
서로 다른 범위에 적용된 특성의 여러 인스턴스 검색
특성의 단일 인스턴스 검색
다음 예제에서는 앞 단원에서 설명한 DeveloperAttribute가 클래스 수준의 MainApp 클래스에 적용됩니다. GetAttribute 메서드는 GetCustomAttribute를 사용하여 클래스 수준의 DeveloperAttribute에 저장된 값을 검색한 다음 이 값을 콘솔에 표시합니다.
Imports System
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
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);
}
}
}
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);
}
}
};
이 프로그램을 실행하면 다음과 같은 텍스트가 표시됩니다.
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 Shared Sub GetAttribute(t As Type)
Dim MyAttributes() As DeveloperAttribute =
CType(Attribute.GetCustomAttributes(t, GetType(DeveloperAttribute)), DeveloperAttribute())
If MyAttributes Is Nothing 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
public static void GetAttribute(Type t)
{
DeveloperAttribute[] MyAttributes =
(DeveloperAttribute[]) Attribute.GetCustomAttributes(t, typeof (DeveloperAttribute));
if (MyAttributes == null)
{
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)
{
array<DeveloperAttribute^>^ MyAttributes =
(array<DeveloperAttribute^>^) Attribute::GetCustomAttributes(t, DeveloperAttribute::typeid);
if (MyAttributes == nullptr)
{
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);
}
}
}
특성이 없으면 이 코드는 사용자에게 경고를 표시합니다. 특성이 있으면 DeveloperAttribute의 두 인스턴스에 들어 있는 정보가 모두 표시됩니다.
서로 다른 범위에 적용된 특성의 여러 인스턴스 검색
GetCustomAttributes 및 GetCustomAttribute 메서드는 전체 클래스를 검색하여 해당 클래스에 있는 특성의 모든 인스턴스를 반환하지는 않습니다. 대신에 지정된 메서드 또는 멤버를 한 번에 하나씩 검색합니다. 동일한 특성이 모든 멤버에 적용된 클래스가 있는 경우 해당 멤버에 적용된 모든 특성에서 값을 검색하려면 GetCustomAttributes 및 GetCustomAttribute에 모든 메서드 또는 멤버를 개별적으로 지정해야 합니다.
다음 코드 예제에서는 클래스를 매개 변수로 사용하고 앞에서 정의한 DeveloperAttribute 를 클래스 수준과 해당 클래스의 모든 개별 메서드에서 검색합니다.
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
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:
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);
}
}
}
메서드 수준 또는 클래스 수준에서 DeveloperAttribute의 인스턴스가 없으면 GetAttribute 메서드는 특성이 없음을 사용자에게 알리고 특성이 없는 메서드 또는 클래스의 이름을 표시합니다. 특성이 있으면 Name, Level 및 Reviewed 필드가 콘솔에 표시됩니다.
Type 클래스의 멤버를 사용하면 전달된 클래스의 개별 메서드 및 멤버를 가져올 수 있습니다. 이 예제에서는 먼저 Type 개체를 쿼리하여 클래스 수준의 특성 정보를 가져옵니다. 그런 다음 Type.GetMethods를 사용하여 모든 메서드의 인스턴스를 System.Reflection.MemberInfo 개체의 배열에 놓아 메서드 수준의 특성 정보를 검색합니다. 또한 Type.GetProperties 메서드를 사용하여 속성 수준의 특성을 확인하거나 Type.GetConstructors 메서드를 사용하여 생성자 수준의 특성을 확인할 수도 있습니다.