Acesse atributos personalizados
Depois que os atributos tiverem sido associados aos elementos do programa, a reflexão poderá ser usada para consultar sua existência e seus valores. O .NET disponibiliza a classe MetadataLoadContext, que você pode usar para examinar o código que não pode ser carregado para execução.
MetadataLoadContext
O código carregado no contexto MetadataLoadContext não pode ser executado. Isso significa que instâncias de atributos personalizados não podem ser criadas porque isso exigiria a execução de seus construtores. Para carregar e analisar os atributos personalizados no contexto CustomAttributeData, use a classe MetadataLoadContext. Você pode obter as instâncias dessa classe usando a sobrecarga apropriada do método CustomAttributeData.GetCustomAttributes estático. Para mais informações, confira Como inspecionar o conteúdo do assembly usando MetadataLoadContext.
O contexto de execução
Os principais métodos de reflexão para consultar atributos no contexto de execução são MemberInfo.GetCustomAttributes e Attribute.GetCustomAttributes.
A acessibilidade de um atributo personalizado é verificada em relação ao assembly ao qual ele está anexado. Isso é equivalente a verificar se um método em um tipo no assembly no qual o atributo personalizado está anexado pode chamar o construtor do atributo personalizado.
Métodos como Assembly.GetCustomAttributes(Boolean) verificam a visibilidade e a acessibilidade do argumento de tipo. Somente o código no assembly que contém o tipo definido pelo usuário pode recuperar um atributo personalizado desse tipo usando GetCustomAttributes
.
O exemplo de C# a seguir é um padrão de design de atributo personalizado típico. Ele ilustra o modelo de reflexão do atributo personalizado em runtime.
System.DLL
public class DescriptionAttribute : Attribute
{
}
System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}
public class LocalizationExtenderProvider
{
[MyDescriptionAttribute(...)]
public CultureInfo GetLanguage(...)
{
}
}
Se o runtime estiver tentando recuperar os atributos personalizados para o tipo de atributo personalizado público DescriptionAttribute anexado ao método GetLanguage
, ele executará as seguintes ações:
- O runtime verifica se o argumento de tipo
DescriptionAttribute
paraType.GetCustomAttributes(Type type)
é público, e portanto está visível e acessível. - O runtime verifica se o tipo definido pelo usuário
MyDescriptionAttribute
, que é derivado deDescriptionAttribute
, está visível e acessível dentro do assembly System.Web.dll, onde está anexado ao métodoGetLanguage()
. - O runtime verifica se o construtor de
MyDescriptionAttribute
está visível e acessível dentro do assembly System.Web.dll. - O runtime chama o construtor de
MyDescriptionAttribute
com os parâmetros do atributo personalizado e retorna o novo objeto para o chamador.
O modelo de reflexão do atributo personalizado pode causar perda de instâncias de tipos definidos pelo usuário fora do assembly no qual o tipo é definido. Isso não é diferente dos membros no sistema da biblioteca runtime que retornam instâncias de tipos definidos pelo usuário, como Type.GetMethods que retorna uma matriz de objetos RuntimeMethodInfo
. Para impedir que um cliente descubra informações sobre um tipo de atributo personalizado definido pelo usuário, defina os membros do tipo como confidenciais.
O exemplo a seguir demonstra a maneira básica de usar a reflexão para obter acesso 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