Acceder a atributos personalizados
Después de asociar atributos a elementos de un programa, puede usar la reflexión para consultar su existencia y sus valores. .NET proporciona el MetadataLoadContext, que se puede usar para examinar el código que no se pueda cargar para su ejecución.
MetadataLoadContext
No se puede ejecutar el código cargado en el contexto de MetadataLoadContext. Esto significa que no se pueden crear instancias de atributos personalizados, porque requeriría la ejecución de sus constructores. Para cargar y examinar los atributos personalizados en el contexto de MetadataLoadContext, use la clase CustomAttributeData. Puede obtener instancias de esta clase mediante la sobrecarga adecuada del método CustomAttributeData.GetCustomAttributes estático. Para más información, consulte Cómo: Inspeccionar el contenido del ensamblado mediante MetadataLoadContext.
Contexto de ejecución
Los principales métodos de reflexión para consultar los atributos en el contexto de ejecución son MemberInfo.GetCustomAttributes y Attribute.GetCustomAttributes.
La accesibilidad de un atributo personalizado se comprueba con respecto al ensamblado al que está asociado. Esto equivale a comprobar si un método en un tipo del ensamblado al que está asociado el atributo personalizado puede llamar al constructor del atributo personalizado.
Los métodos como Assembly.GetCustomAttributes(Boolean) comprueban la visibilidad y la accesibilidad del argumento de tipo. Solo el código del ensamblado que contenga el tipo definido por el usuario puede recuperar un atributo personalizado de ese tipo mediante GetCustomAttributes
.
El siguiente ejemplo de C# es un modelo de diseño típico de atributos personalizados en el que se muestra el modelo de reflexión de atributos personalizados en tiempo de ejecución.
System.DLL
public class DescriptionAttribute : Attribute
{
}
System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}
public class LocalizationExtenderProvider
{
[MyDescriptionAttribute(...)]
public CultureInfo GetLanguage(...)
{
}
}
Si el tiempo de ejecución intenta recuperar los atributos personalizados para el tipo de atributo personalizado público DescriptionAttribute asociado al método GetLanguage
, realiza las acciones siguientes:
- El tiempo de ejecución comprueba que el argumento de tipo
DescriptionAttribute
aType.GetCustomAttributes(Type type)
sea público y, por tanto, sea visible y accesible. - El tiempo de ejecución comprueba que el tipo definido por el usuario
MyDescriptionAttribute
que se deriva deDescriptionAttribute
sea visible y accesible en el ensamblado System.Web.dll, donde está asociado al métodoGetLanguage()
. - El tiempo de ejecución comprueba que el constructor de
MyDescriptionAttribute
sea visible y accesible dentro del ensamblado System.Web.dll. - El tiempo de ejecución llama al constructor de
MyDescriptionAttribute
con los parámetros de atributo personalizados y devuelve el nuevo objeto al autor de la llamada.
En el modelo de reflexión de atributos personalizados, pueden producirse pérdidas de instancias de tipos definidos por el usuario fuera del ensamblado donde está definido el tipo. Esto no es diferente de los miembros de la biblioteca del sistema en tiempo de ejecución que devuelven instancias de tipos definidos por el usuario, como cuando Type.GetMethods devuelve una matriz de objetos RuntimeMethodInfo
. Para evitar que a un cliente detecte información sobre un tipo de atributo personalizado definido por el usuario, defina los miembros del tipo como no públicos.
En el ejemplo siguiente se muestra la forma básica de usar la reflexión para obtener acceso a atributos personalizados.
using namespace System;
public ref class ExampleAttribute : Attribute
{
private:
String^ stringVal;
public:
ExampleAttribute()
{
stringVal = "This is the default string.";
}
property String^ StringValue
{
String^ get() { return stringVal; }
void set(String^ value) { stringVal = value; }
}
};
[Example(StringValue="This is a string.")]
public ref class Class1
{
public:
static void Main()
{
System::Reflection::MemberInfo^ info = Type::GetType("Class1");
for each (Object^ attrib in info->GetCustomAttributes(true))
{
Console::WriteLine(attrib);
}
}
};
int main()
{
Class1::Main();
}
using System;
public class ExampleAttribute : Attribute
{
private string stringVal;
public ExampleAttribute()
{
stringVal = "This is the default string.";
}
public string StringValue
{
get { return stringVal; }
set { stringVal = value; }
}
}
[Example(StringValue="This is a string.")]
class Class1
{
public static void Main()
{
System.Reflection.MemberInfo info = typeof(Class1);
foreach (object attrib in info.GetCustomAttributes(true))
{
Console.WriteLine(attrib);
}
}
}
Public Class ExampleAttribute
Inherits Attribute
Private stringVal As String
Public Sub New()
stringVal = "This is the default string."
End Sub
Public Property StringValue() As String
Get
Return stringVal
End Get
Set(Value As String)
stringVal = Value
End Set
End Property
End Class
<Example(StringValue:="This is a string.")> _
Class Class1
Public Shared Sub Main()
Dim info As System.Reflection.MemberInfo = GetType(Class1)
For Each attrib As Object In info.GetCustomAttributes(true)
Console.WriteLine(attrib)
Next attrib
End Sub
End Class