Condividi tramite


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 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, Levele 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.");
        }
    }
}

Vedere anche