Share via


Accéder aux attributs personnalisés

Une fois que des attributs associés aux éléments de programme, la réflexion peut être utilisée pour interroger leur existence et leurs valeurs. .NET fournit le MetadataLoadContext, que vous pouvez utiliser pour examiner le code qui ne peut pas être chargé à des fins d’exécution.

MetadataLoadContext

Le code chargé dans le contexte MetadataLoadContext ne peut pas être exécuté. Cela signifie que des instances d’attributs personnalisés ne peuvent pas être créées, car cela nécessiterait l’exécution de leurs constructeurs. Pour charger et examiner des attributs personnalisés dans le contexte de CustomAttributeData, utilisez la classe MetadataLoadContext. Vous pouvez obtenir des instances de cette classe à l’aide de la surcharge appropriée de la méthode statique CustomAttributeData.GetCustomAttributes. Pour plus d’informations, consultez Guide pratique pour inspecter le contenu de l’assembly à l’aide de MetadataLoadContext.

Contexte d’exécution

Les principales méthodes de réflexion pour interroger les attributs dans le contexte d’exécution sont MemberInfo.GetCustomAttributes et Attribute.GetCustomAttributes.

L’accessibilité d’un attribut personnalisé est vérifiée par rapport à l’assembly dans lequel il est attaché. Cela équivaut à vérifier si une méthode sur un type dans l’assembly dans lequel l’attribut personnalisé est attaché peut appeler le constructeur de l’attribut personnalisé.

Les méthodes comme Assembly.GetCustomAttributes(Boolean) vérifient la visibilité et l’accessibilité de l’argument de type. Seul le code dans l’assembly qui contient le type défini par l’utilisateur peut récupérer un attribut personnalisé de ce type à l’aide de GetCustomAttributes.

L’exemple C# suivant est un modèle de conception d’attribut personnalisé classique. Il illustre le modèle de réflexion d’attribut personnalisé du runtime.

System.DLL
public class DescriptionAttribute : Attribute
{
}

System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}

public class LocalizationExtenderProvider
{
    [MyDescriptionAttribute(...)]
    public CultureInfo GetLanguage(...)
    {
    }
}

Si le runtime tente de récupérer les attributs personnalisés pour le type d’attribut personnalisé public DescriptionAttribute attaché à la méthode GetLanguage, il effectue les actions suivantes :

  1. Le runtime vérifie que l’argument de type DescriptionAttribute de Type.GetCustomAttributes(Type type) est public, et donc visible et accessible.
  2. Le runtime vérifie que le type défini par l’utilisateur MyDescriptionAttribute qui est dérivé de DescriptionAttribute est visible et accessible dans l’assembly System.Web.dll, où il est attaché à la méthode GetLanguage().
  3. Le runtime vérifie que le constructeur de MyDescriptionAttribute est visible et accessible dans l’assembly System.Web.dll.
  4. Le runtime appelle le constructeur de MyDescriptionAttribute avec les paramètres de l’attribut personnalisé et retourne le nouvel objet à l’appelant.

Le modèle de réflexion d’attribut personnalisé peut laisser fuiter des instances de types définis par l’utilisateur en dehors de l’assembly dans lequel le type est défini. Cela équivaut aux membres de la bibliothèque système du runtime qui retournent des instances de types définis par l’utilisateur, comme Type.GetMethods retournant un tableau d’objets RuntimeMethodInfo. Pour empêcher un client de découvrir des informations relatives à un type d’attribut personnalisé défini par l’utilisateur, définissez les membres du type comme étant non publics.

L’exemple suivant montre comment utiliser simplement la réflexion pour accéder à des attributs personnalisés.

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

Voir aussi