Accesso ad attributi personalizzati
Dopo che gli attributi sono stati associati a elementi del programma, è possibile verificarne l'esistenza ed esaminarne il valore tramite reflection. In .NET Framework versioni 1.0 e 1.1 gli attributi personalizzati vengono esaminati nel contesto di esecuzione. In .NET Framework versione 2.0 è disponibile un nuovo contesto di caricamento, Reflection-Only, che consente di esaminare il codice che non è possibile caricare per l'esecuzione.
Contesto Reflection-Only
Il codice caricato nel contesto Reflection-Only non può essere eseguito. Non è pertanto possibile creare istanze di attributi personalizzati, operazione per cui è richiesta l'esecuzione dei costruttori. Per caricare ed esaminare gli attributi personalizzati nel contesto Reflection-Only, utilizzare la classe CustomAttributeData. È possibile ottenere istanze di questa classe utilizzando l'overload appropriato del metodo statico CustomAttributeData.GetCustomAttributes. Per informazioni al riguardo, vedere Procedura: caricare assembly nel contesto Reflection-Only.
Contesto di esecuzione
I principali metodi di reflection per l'esecuzione di query sugli attributi nel contesto di esecuzione sono MemberInfo.GetCustomAttributes e Attribute.GetCustomAttributes.
L'accessibilità di un attributo personalizzato viene controllata in riferimento all'assembly a cui l'attributo è collegato. In altri termini, si verifica se un metodo di un tipo dell'assembly a cui è collegato l'attributo personalizzato può chiamare il costruttore dell'attributo personalizzato.
I metodi come Assembly.GetCustomAttributes(Boolean) consentono di controllare la visibilità e l'accessibilità dell'argomento di tipo. È possibile recuperare un attributo personalizzato del tipo definito dall'utente tramite GetCustomAttributes solo nel codice dell'assembly che contiene tale tipo.
Nell'esempio in C# riportato di seguito viene rappresentato un tipico modello di progettazione di attributi personalizzati. Viene illustrato il modello di reflection degli attributi personalizzati adottato dal runtime.
System.DLL
public class DescriptionAttribute : Attribute
{
}
System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}
public class LocalizationExtenderProvider
{
[MyDescriptionAttribute(...)]
public CultureInfo GetLanguage(...)
{
}
}
Se il runtime tenta di recuperare gli attributi personalizzati del tipo di attributo personalizzato pubblico DescriptionAttribute associato al metodo GetLanguage, effettua le seguenti operazioni:
Controlla che l'argomento di tipo DescriptionAttribute per Type.GetCustomAttributes(Type tipo) sia pubblico e quindi visibile e accessibile.
Controlla che il tipo definito dall'utente MyDescriptionAttribute derivato da DescriptionAttribute sia visibile e accessibile all'interno dell'assembly System.Web.DLL, in cui è collegato al metodo GetLanguage().
Controlla che il costruttore di MyDescriptionAttribute sia visibile e accessibile all'interno dell'assembly System.Web.DLL.
Chiama il costruttore di MyDescriptionAttribute con i parametri dell'attributo personalizzato e restituisce il nuovo oggetto al chiamante.
Il modello di reflection degli attributi personalizzati può perdere istanze di tipi definiti dall'utente all'esterno dell'assembly in cui il tipo è definito. Questo modello non differisce da quello in cui si inquadrano i membri della libreria di sistema del runtime, che restituiscono istanze di tipi definiti dall'utente, quali Type.GetMethods(), che restituisce una matrice di oggetti RuntimeMethodInfo. Per impedire a un client di rilevare informazioni su un attributo personalizzato definito dall'utente, definire i membri del tipo come non pubblici.
Nell'esempio che segue viene illustrato il metodo principale per accedere agli attributi personalizzati tramite reflection.
Imports System
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
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);
}
}
}
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();
}
Vedere anche
Riferimenti
MemberInfo.GetCustomAttributes