Recupero di informazioni archiviate negli attributi
Il recupero di un attributo personalizzato è un processo semplice. Prima di tutto, dichiarare un'istanza dell'attributo da recuperare. Usare quindi il metodo Attribute.GetCustomAttribute per inizializzare il nuovo attributo sul valore dell'attributo da recuperare. Dopo aver inizializzato il nuovo attributo, è possibile usare le relative proprietà per ottenere i valori.
Importante
Questo articolo descrive come recuperare gli attributi per il codice caricato nel contesto di esecuzione. Per recuperare gli attributi per il codice caricato nel contesto di sola riflessione, è necessario usare la classe CustomAttributeData, come illustrato in Procedura: Caricare gli assembly nel contesto Reflection-Only.
In questa sezione vengono descritti i modi seguenti per recuperare gli attributi:
Recupero di più istanze di un attributo applicato allo stesso ambito
Recupero di più istanze di un attributo applicato a ambiti diversi
Recupero di una singola istanza di un attributo
Nell'esempio seguente il DeveloperAttribute
(descritto nella sezione precedente) viene applicato alla classe MainApp
a livello di classe. Il metodo GetAttribute
usa GetCustomAttribute
per recuperare i valori archiviati in DeveloperAttribute
a livello di classe prima di visualizzarli nella console.
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
L'esecuzione del programma precedente visualizza il testo seguente:
The Name Attribute is: Joan Smith.
The Level Attribute is: 42.
The Reviewed Attribute is: True.
Se l'attributo non viene trovato, il metodo GetCustomAttribute
inizializza MyAttribute
su un valore Null. Questo esempio controlla MyAttribute
per tale istanza e notifica all'utente se l'attributo non viene trovato. Se DeveloperAttribute
non viene trovato nell'ambito della classe, nella console viene visualizzato il messaggio seguente:
The attribute was not found.
Nell'esempio precedente si presuppone che la definizione dell'attributo si trova nello spazio dei nomi corrente. Ricordarsi di importare lo spazio dei nomi in cui risiede la definizione dell'attributo se non si trova nello spazio dei nomi corrente.
Recupero di più istanze di un attributo applicato allo stesso ambito
Nell'esempio precedente la classe da esaminare e l'attributo specifico da trovare vengono passati al metodo GetCustomAttribute. Questo codice funziona correttamente se viene applicata una sola istanza di un attributo a livello di classe. Tuttavia, se più istanze di un attributo vengono applicate allo stesso livello di classe, il metodo GetCustomAttribute
non recupera tutte le informazioni. Nei casi in cui più istanze dello stesso attributo vengono applicate allo stesso ambito, è possibile usare Attribute.GetCustomAttributes metodo per inserire tutte le istanze di un attributo in una matrice. Ad esempio, se due istanze di DeveloperAttribute
vengono applicate a livello di classe della stessa classe, il metodo GetAttribute
può essere modificato per visualizzare le informazioni disponibili in entrambi gli attributi. Ricorda di applicare più attributi allo stesso livello. L'attributo deve essere definito con la proprietà AllowMultiple
impostata su true
nella classe AttributeUsageAttribute.
Nell'esempio di codice seguente viene illustrato come usare il metodo GetCustomAttributes
per creare una matrice che faccia riferimento a tutte le istanze di DeveloperAttribute
in una determinata classe. Il codice restituisce quindi i valori di tutti gli attributi nella console.
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
Se non vengono trovati attributi, questo codice avvisa l'utente. In caso contrario, vengono visualizzate le informazioni contenute in entrambe le istanze di DeveloperAttribute
.
Recupero di più istanze di un attributo applicato a ambiti diversi
I metodi GetCustomAttributes e GetCustomAttribute non eseguono ricerche in un'intera classe e restituiscono tutte le istanze di un attributo in tale classe. Piuttosto, eseguono la ricerca di un solo metodo o membro specificato alla volta. Se si dispone di una classe con lo stesso attributo applicato a ogni membro e si desidera recuperare i valori in tutti gli attributi applicati a tali membri, è necessario fornire ogni metodo o membro singolarmente a GetCustomAttributes
e GetCustomAttribute
.
L'esempio di codice seguente accetta una classe come parametro e cerca il DeveloperAttribute
(definito in precedenza) a livello di classe e su ogni singolo metodo della classe:
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
Se nessuna istanza del DeveloperAttribute
viene trovata a livello di metodo o classe, il metodo GetAttribute
notifica all'utente che non sono stati trovati attributi e visualizza il nome del metodo o della classe che non contiene l'attributo. Se viene trovato un attributo, nella console vengono visualizzati i campi Name
, Level
e Reviewed
.
È possibile usare i membri della classe Type per ottenere i singoli metodi e membri nella classe passata. Questo esempio esegue prima una query sull'oggetto Type
per ottenere informazioni sull'attributo per il livello di classe. Usa quindi Type.GetMethods per inserire istanze di tutti i metodi in una matrice di oggetti System.Reflection.MemberInfo per recuperare le informazioni sugli attributi per il livello del metodo. È anche possibile usare il metodo Type.GetProperties per verificare la presenza di attributi a livello di proprietà o Type.GetConstructors per verificare la presenza di attributi a livello di costruttore.
Recupero di attributi dai membri di una classe
Oltre a recuperare attributi a livello di classe, gli attributi possono essere applicati anche a singoli membri, ad esempio metodi, proprietà e campi. I metodi GetCustomAttribute
e GetCustomAttributes
possono essere usati per recuperare questi attributi.
Esempio
Nell'esempio seguente viene illustrato come recuperare un attributo applicato a un metodo:
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.");
}
}
}