Zugreifen auf benutzerdefinierte Attribute

Nach der Verknüpfung von Attributen mit Programmelementen ist es möglich, ihr Vorhandensein sowie ihre Werte unter Verwendung von Reflektion abzufragen. In den .NET Framework-Versionen 1.0 und 1.1 werden benutzerdefinierte Attribute im Ausführungskontext untersucht. In .NET Framework, Version 2.0 steht ein neuer Load-Kontext, der reflektionsbezogene Kontext zur Verfügung, um Code zu untersuchen, der nicht für die Ausführung geladen werden kann.

Reflektionsbezogener Kontext

Code, der in den reflektionsbezogenen Kontext geladen wird, kann nicht ausgeführt werden. Daher können keine Instanzen benutzerdefinierter Attribute erstellt werden, da hierfür die zugehörigen Konstruktoren ausgeführt werden müssten. Benutzerdefinierte Attribute können im reflektionsbezogenen Kontext mithilfe der CustomAttributeData-Klasse geladen und untersucht werden. Sie können Instanzen dieser Klasse durch die entsprechende Überladung der statischen CustomAttributeData.GetCustomAttributes-Methode erhalten. Siehe Gewusst wie: Laden von Assemblys in den reflektionsbezogenen Kontext.

Ausführungskontext

Die Hauptreflektionsmethoden zum Abfragen von Attributen im Ausführungskontext sind MemberInfo.GetCustomAttributes und Attribute.GetCustomAttributes.

Die Zugriffsmöglichkeit auf ein benutzerdefiniertes Attribut wird unter Berücksichtigung der Assembly geprüft, mit der es verknüpft ist. Äquivalent dazu ist die Überprüfung, ob eine Methode für einen Typ in der Assembly, mit der das benutzerdefinierte Attribut verknüpft ist, den Konstruktor des benutzerdefinierten Attributs aufrufen kann.

Methoden wie Assembly.GetCustomAttributes(Boolean) überprüfen die Sichtbarkeit und den Zugriff des Typarguments. Nur Code in der Assembly, die den benutzerdefinierten Typ enthält, kann mithilfe von GetCustomAttributes ein benutzerdefiniertes Attribut dieses Typs abrufen.

Das folgende C#-Beispiel ist ein typisches Entwurfsmuster für ein benutzerdefiniertes Attribut. Das Beispiel verdeutlicht das Reflektionsmodell der Common Language Runtime mit benutzerdefinierten Attributen.

System.DLL
public class DescriptionAttribute : Attribute
{
}

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

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

Wenn die Laufzeit versucht, die benutzerdefinierten Attribute für den öffentlichen benutzerdefinierten Attributtyp DescriptionAttribute abzurufen, der mit der GetLanguage-Methode verknüpft ist, werden folgende Aktionen durchgeführt:

  1. Common Language Runtime überprüft, ob das Typargument DescriptionAttribute für Type.GetCustomAttributes (Type Typ) öffentlich ist, d. h. sichtbar und erreichbar.

  2. Common Language Runtime überprüft, ob der von der DescriptionAttribute abgeleitete benutzerdefinierte MyDescriptionAttribute-Typ innerhalb der System.Web.DLL-Assembly sichtbar und erreichbar ist. Darin ist der MyDescriptionAttribute-Typ mit der GetLanguage()-Methode verknüpft.

  3. Common Language Runtime überprüft, ob der Konstruktor von MyDescriptionAttribute innerhalb der System.Web.DLL-Assembly sichtbar und erreichbar ist.

  4. Common Language Runtime ruft den Konstruktor von MyDescriptionAttribute mit den benutzerdefinierten Attributparametern auf und gibt das neue Objekt an den Anrufer zurück.

Durch das Reflektionsmodell mit benutzerdefinierten Attributen können Instanzen benutzerdefinierter Typen aus der Assembly verloren gehen, in der der Typ definiert ist. Dies gilt auch für Member der Laufzeitsystembibliothek, die Instanzen benutzerdefinierter Typen zurückgeben, z. B. Type.GetMethods(), wodurch die Rückgabe eines Arrays von RuntimeMethodInfo-Objekten erfolgt. Um zu verhindern, dass ein Client Informationen über einen benutzerdefinierten Attributtyp ermitteln kann, müssen Sie die Member dieses Typs als nicht öffentlich definieren.

Folgendes Beispiel zeigt, wie Reflektion im Prinzip verwendet werden kann, um Zugriff auf benutzerdefinierte Attribute zu erhalten.

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();
}

Siehe auch

Referenz

MemberInfo.GetCustomAttributes

Attribute.GetCustomAttributes

Konzepte

Anzeigen von Typinformationen

Sicherheitsüberlegungen für die Reflektion