Recuperar información almacenada en atributos

Actualización: noviembre 2007

La recuperación de un atributo personalizado es un proceso simple. En primer lugar, se ha de declarar una instancia del atributo que se desee recuperar. A continuación, utilice el método Attribute.GetCustomAttribute para inicializar el atributo nuevo en el valor del atributo que se desee recuperar. Una vez inicializado el atributo nuevo, basta con utilizar sus propiedades para obtener los valores.

Nota importante:

Este tema describe cómo recuperar los atributos de código cargado en el contexto de ejecución. Con el fin de recuperar atributos para código cargado en el contexto de sólo reflexión, debe utilizar la clase CustomAttributeData, como se muestra en Cómo: Cargar ensamblados en el contexto de sólo reflexión.

Esta sección describe los métodos siguientes para recuperar atributos:

  • Recuperar una sola instancia de un atributo

  • Recuperar varias instancias de un atributo aplicadas al mismo ámbito

  • Recuperar varias instancias de un atributo aplicadas a ámbitos diferentes

Recuperar una sola instancia de un atributo

En el ejemplo siguiente, el atributo DeveloperAttribute (descrito en la sección anterior) se aplica a la clase MainApp en el nivel de clase. El método GetAttribute utiliza GetCustomAttribute para recuperar los valores almacenados en DeveloperAttribute en el nivel de clase antes de mostrarlos en la consola.

using System;

[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(null == MyAttribute)
            {
                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

<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

Este programa muestra el texto siguiente cuando se ejecuta.

The Name Attribute is: Joan Smith.
The Level Attribute is: 42.
The Reviewed Attribute is: True.

Si no se encuentra el atributo, el método GetCustomAttribute inicializa MyAttribute en un valor nulo. En este ejemplo se comprueba MyAttribute para una instancia de este tipo y se avisa al usuario si no se encuentra ningún atributo. Si no se encuentra el atributo DeveloperAttribute en el ámbito de clases, se muestra el mensaje siguiente en la consola.

The attribute was not found. 

En este ejemplo se supone que la definición de atributo está en el espacio de nombres actual. Recuerde que se ha de importar el espacio de nombres en que reside la definición de atributo si no está en el espacio de nombres actual.

Recuperar varias instancias de un atributo aplicadas al mismo ámbito

En el ejemplo anterior, la clase que se desea inspeccionar y el atributo específico que se desea buscar se pasan como parámetros a GetCustomAttribute. Ese código funciona correctamente si se aplica una sola instancia de un atributo en el nivel de clase. Sin embargo, si se aplican varias instancias de un atributo en el mismo nivel de clase, el método GetCustomAttribute no recupera toda la información. En los casos en que se aplican varias instancias del mismo atributo al mismo ámbito se puede utilizar Attribute.GetCustomAttributes para colocar todas las instancias de un atributo en una matriz. Por ejemplo, si dos instancias del atributo DeveloperAttribute se aplican en el nivel de clase de la misma clase, el método GetAttribute se puede modificar para que se muestre la información encontrada en ambos atributos. Recuerde que, para aplicar varios atributos en el mismo nivel, el atributo se debe definir con la propiedad AllowMultiple establecida en true en el atributo AttributeUsageAttribute.

El ejemplo de código siguiente muestra cómo se utiliza el método GetCustomAttributes para crear una matriz que hace referencia a todas las instancias de DeveloperAttribute en una clase dada. Los valores de todos los atributos se muestran después en la consola.

public static void GetAttribute(Type t)
{
    DeveloperAttribute[] MyAttribute =
    (DeveloperAttribute[]) Attribute.GetCustomAttributes(t, typeof (DeveloperAttribute));
    
    if(null == MyAttribute)
    {
        Console.WriteLine("The attribute was not found.");
    }
    else
    {
        for(int i = 0 ; i < MyAttribute.Length ; i++)
        {
            //Get the Name value.    
            Console.WriteLine("The Name Attribute is: {0}." , MyAttribute[i].Name);
            //Get the Level value.  
            Console.WriteLine("The Level Attribute is: {0}." , MyAttribute[i].Level);
            //Get the Reviewed value.
            Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute[i].Reviewed);
        }
    }
}
Public Shared Sub GetAttribute(t As Type)
    Dim MyAttribute As DeveloperAttribute() = _
    CType(Attribute.GetCustomAttributes(t, GetType(DeveloperAttribute)), DeveloperAttribute())
       
    If MyAttribute Is Nothing Then
        Console.WriteLine("The attribute was not found.")
    Else
        Dim i As Integer
        For i = 0 To MyAttribute.Length - 1
            'Get the Name value. 
            Console.WriteLine("The Name Attribute is: {0}.", MyAttribute(i).Name)
            'Get the Level value.   
            Console.WriteLine("The Level Attribute is: {0}.", MyAttribute(i).Level)
            'Get the Reviewed value.
            Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute(i).Reviewed)
        Next i
    End If
End Sub

Si no se encuentran atributos, este código avisa al usuario. En caso contrario, se muestra la información contenida en ambas instancias de DeveloperAttribute.

Recuperar varias instancias de un atributo aplicadas a ámbitos diferentes

Los métodos GetCustomAttributes y GetCustomAttribute no buscan una clase completa y devuelven todas las instancias de un atributo de esa clase. En su lugar, sólo buscan un miembro o un método especificado cada vez. Si se tiene una clase con el mismo atributo aplicado a todos los miembros y se desea recuperar los valores de todos los atributos aplicados a dichos miembros, se debe proporcionar cada uno de los métodos o de los miembros individualmente a GetCustomAttributes y GetCustomAttribute.

En el ejemplo de código siguiente se toma una clase como parámetro y se busca el atributo DeveloperAttribute (definido previamente) en el nivel de clase y en todos los métodos individuales de esa clase.

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(null == att)
    {
        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(null == att)
        {
            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 Then
        Console.WriteLine("No attribute in class {0}.", t.ToString())
        Console.WriteLine()
    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}.", att.Reviewed)
        Console.WriteLine()
    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.
    Dim i As Integer
    For i = 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}.", MyMemberInfo(i).ToString())
            Console.WriteLine()
        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}.", MyMemberInfo(i).ToString(), att.Reviewed)
            Console.WriteLine()
        End If
    Next i
End Sub

Si no se encuentran instancias del atributo DeveloperAttribute en el nivel de método o nivel de clase, el método GetAttribute notifica al usuario que no se han encontrado atributos y muestra el nombre del método o de la clase que no contiene el atributo. Si se encuentra un atributo, los campos Name, Level y Reviewed se muestran en la consola.

Se pueden utilizar los miembros de la clase Type para obtener los miembros y métodos individuales de la clase pasada como parámetro. En este ejemplo se consulta primero el objeto Type para obtener información de atributos para el nivel de clase. A continuación, utiliza Type.GetMethods para colocar las instancias de todos los métodos en una matriz de objetos System.Reflection.MemberInfo para recuperar la información de atributos en el nivel del método. También puede utilizar el método Type.GetProperties para comprobar los atributos en el nivel de propiedad o el método Type.GetConstructors para comprobar los atributos en el nivel de constructor.

Vea también

Referencia

System.Type

Attribute.GetCustomAttribute

Attribute.GetCustomAttributes

Otros recursos

Extender metadatos mediante atributos