Verfassen von benutzerdefinierten Attributen

Zum Entwerfen eigener benutzerdefinierter Attribute müssen Sie keine neuen Verfahren erlernen. Wenn Sie mit dem objektorientierten Programmieren vertraut sind und Klassen entwerfen können, verfügen Sie bereits über die wichtigsten Kenntnisse. Benutzerdefinierte Attribute sind im Prinzip herkömmliche Klassen, die direkt oder indirekt von System.Attribute abgeleitet werden. Wie herkömmliche Klassen enthalten benutzerdefinierte Attribute Methoden zum Speichern und Abrufen von Daten.

Dies sind die ersten Schritte zum ordnungsgemäßen Entwerfen benutzerdefinierter Attributklassen:

  • Anwenden von AttributeUsageAttribute

  • Deklarieren der Attributklasse

  • Deklarieren von Konstruktoren

  • Deklarieren von Eigenschaften

Dieser Abschnitt beschreibt die einzelnen Schritte und endet mit einem Beispiel für ein benutzerdefiniertes Attribut.

Anwenden von AttributeUsageAttribute

Die Deklaration eines benutzerdefinierten Attributs beginnt mit AttributeUsageAttribute. Hiermit werden einige der wichtigsten Eigenschaften der Attributklasse definiert. Sie können z. B. angeben, ob das Attribut von anderen Klassen geerbt und auf welche Elemente das Attribut angewendet werden kann. Im folgenden Codefragment wird die Verwendung von AttributeUsageAttribute dargestellt.

<AttributeUsage(AttributeTargets.All, Inherited := False, AllowMultiple := True)>
Public Class SomeClass
    Inherits Attribute
    '...
End Class
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
[AttributeUsage(AttributeTargets::All, Inherited = false, AllowMultiple = true)]

Das System.AttributeUsageAttribute verfügt über drei Member, die für das Erstellen benutzerdefinierter Attribute wichtig sind: AttributeTargets, Inherited und AllowMultiple.

AttributeTargets-Member

Im vorherigen Beispiel wurde AttributeTargets.Allfestgelegt. Dies gibt an, dass das Attribut auf alle Programmelemente angewendet werden kann. Sie können auch AttributeTargets.Class festlegen und damit angeben, dass das Attribut nur auf eine Klasse angewendet werden kann, oder AttributeTargets.Method, um anzugeben, dass das Attribut nur auf eine Methode angewendet werden kann. So können alle Programmelemente durch ein benutzerdefiniertes Attribut für die Beschreibung gekennzeichnet werden.

Sie können auch mehrere Instanzen von AttributeTargets übergeben. Im folgenden Codefragment wird angegeben, dass ein benutzerdefiniertes Attribut auf beliebige Klassen bzw. Methoden angewendet werden kann.

<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method)>
Public Class SomeOtherClass
    Inherits Attribute
    '...
End Class
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
[AttributeUsage(AttributeTargets::Class | AttributeTargets::Method)]

Inherited-Eigenschaft

Die Inherited-Eigenschaft gibt an, ob das Attribut von Klassen geerbt werden kann, die von den Klassen abgeleitet wurden, auf die das Attribut angewendet wird. Diese Eigenschaft benötigt entweder das Flag true (Standardeinstellung) oder das Flag false. Im folgenden Beispiel hat MyAttribute z. B. den als Standard festgelegten Inherited-Wert true, während YourAttribute den Inherited-Wert false hat.

' This defaults to Inherited = true.
Public Class MyAttribute
    Inherits Attribute
    '...
End Class

<AttributeUsage(AttributeTargets.Method, Inherited := False)>
Public Class YourAttribute
    Inherits Attribute
    '...
End Class
// This defaults to Inherited = true.
public class MyAttribute : Attribute
{
    //...
}

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
    //...
}
// This defaults to Inherited = true.
public ref class MyAttribute : Attribute
{
    //...
};

[AttributeUsage(AttributeTargets::Method, Inherited = false)]
public ref class YourAttribute : Attribute
{
    //...
};

Dann werden beide Attribute auf eine Methode in der Basisklasse MyClass angewendet.

Public Class MeClass
    <MyAttribute>
    <YourAttribute>
    Public Overridable Sub MyMethod()
        '...
    End Sub
End Class
public class MyClass
{
    [MyAttribute]
    [YourAttribute]
    public virtual void MyMethod()
    {
        //...
    }
}
public ref class MyClass
{
public:
    [MyAttribute]
    [YourAttribute]
    virtual void MyMethod()
    {
        //...
    }
};

Schließlich wird die Klasse YourClass von der Basisklasse MyClass geerbt. Die Methode MyMethod zeigt MyAttribute, jedoch nicht YourAttribute.

Public Class YourClass
    Inherits MeClass
    ' MyMethod will have MyAttribute but not YourAttribute.
    Public Overrides Sub MyMethod()
        '...
    End Sub

End Class
public class YourClass : MyClass
{
    // MyMethod will have MyAttribute but not YourAttribute.
    public override void MyMethod()
    {
        //...
    }

}
public ref class YourClass : MyClass
{
public:
    // MyMethod will have MyAttribute but not YourAttribute.
    virtual void MyMethod() override
    {
        //...
    }

};

AllowMultiple-Eigenschaft

Die AllowMultiple-Eigenschaft gibt an, ob mehrere Instanzen eines Attributs für ein Element vorhanden sein können. Wenn sie auf true festgelegt ist, sind mehrere Instanzen zulässig. Wenn sie auf false (Standardeinstellung) festgelegt ist, ist nur eine Instanz zulässig.

Im folgenden Codebeispiel hat MyAttribute den als Standard festgelegten AllowMultiple-Wert false, während YourAttribute den Wert true hat.

' This defaults to AllowMultiple = false.
Public Class MyAttribute
    Inherits Attribute
End Class

<AttributeUsage(AttributeTargets.Method, AllowMultiple := true)>
Public Class YourAttribute
    Inherits Attribute
End Class
//This defaults to AllowMultiple = false.
public class MyAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
//This defaults to AllowMultiple = false.
public ref class MyAttribute : Attribute
{
};

[AttributeUsage(AttributeTargets::Method, AllowMultiple = true)]
public ref class YourAttribute : Attribute
{
};

Wenn mehrere Instanzen dieser Attribute angewendet werden, erzeugt MyAttribute einen Compilerfehler. Das folgende Codebeispiel veranschaulicht die gültige Verwendung von YourAttribute und die ungültige Verwendung von MyAttribute.

Public Class MyClass
    ' This produces an error.
    ' Duplicates are not allowed.
    <MyAttribute>
    <MyAttribute>
    Public Sub MyMethod()
        '...
    End Sub

    ' This is valid.
    <YourAttribute>
    <YourAttribute>
    Public Sub YourMethod()
        '...
    End Sub
End Class
public class MyClass
{
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute]
    [MyAttribute]
    public void MyMethod()
    {
        //...
    }

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    public void YourMethod()
    {
        //...
    }
}
public ref class MyClass
{
public:
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute]
    [MyAttribute]
    void MyMethod()
    {
        //...
    }

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    void YourMethod()
    {
        //...
    }
};

Wenn sowohl für die AllowMultiple-Eigenschaft als auch für die Inherited-Eigenschaft true festgelegt ist, kann eine von einer anderen Klasse geerbte Klasse ein Attribut erben und die Anwendung einer anderen Instanz desselben Attributs in derselben untergeordneten Klasse zulassen. Wenn AllowMultiple auf false festgelegt ist, werden die Werte der Attribute in der übergeordneten Klasse durch beliebige neue Instanzen desselben Attributs in der untergeordneten Klasse überschrieben.

Deklarieren der Attributklasse

Nach dem Anwenden von AttributeUsageAttribute können Sie beginnen, die spezifischen Merkmale des Attributs zu definieren. Die Deklaration einer Attributklasse ähnelt der Deklaration einer herkömmlichen Klasse, wie das folgende Codebeispiel veranschaulicht.

<AttributeUsage(AttributeTargets.Method)>
Public Class MyAttribute
    Inherits Attribute
    ' . . .
End Class
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
    // . . .
}
[AttributeUsage(AttributeTargets::Method)]
public ref class MyAttribute : Attribute
{
    // . . .
};

Mit dieser Attributdefinition werden die folgenden Punkte veranschaulicht:

  • Attributklassen müssen als öffentliche Klassen deklariert werden.

  • Die Konvention besagt, dass der Name der Attributklasse mit dem Word Attribute endet . Auch wenn diese Konvention keine Vorschrift darstellt, so dient sie doch der besseren Lesbarkeit. Beim Anwenden des Attributs ist das Einschließen des Wortes "Attribute" freigestellt.

  • Alle Attributklassen müssen direkt oder indirekt von System.Attribute erben.

  • In Microsoft Visual Basic müssen alle benutzerdefinierten Attributklassen über das AttributeUsageAttribute-Attribut verfügen.

Deklarieren von Konstruktoren

Attribute werden genau wie herkömmliche Klassen mit Konstruktoren initialisiert. Im folgenden Codefragment wird ein typischer Konstruktor eines Attributs dargestellt. Dieser öffentliche Konstruktor akzeptiert einen Parameter und legt dessen Wert auf den einer Membervariablen fest.

Public Sub New(myvalue As Boolean)
    Me.myvalue = myvalue
End Sub
public MyAttribute(bool myvalue)
{
    this.myvalue = myvalue;
}
MyAttribute(bool myvalue)
{
    this->myvalue = myvalue;
}

Sie können den Konstruktor überladen, um verschiedene Kombinationen von Werten zu ermöglichen. Wenn Sie außerdem eine Eigenschaft für die benutzerdefinierte Attributklasse definieren, können Sie beim Initialisieren des Attributs eine Kombination benannter und positionaler Parameter verwenden. Normalerweise definieren Sie alle erforderlichen Parameter als positional und alle optionalen Parameter als benannt. In diesem Fall kann das Attribut nicht ohne den erforderlichen Parameter initialisiert werden. Alle übrigen Parameter sind optional. Beachten Sie, dass Konstruktoren für ein Attribut in Visual Basic kein ParamArray-Argument verwenden sollten.

Das folgende Codebeispiel veranschaulicht die Anwendung eines Attributs, das den vorherigen Konstruktor verwendet, mit optionalen und erforderlichen Parametern. Dabei wird vorausgesetzt, dass das Attribut über einen erforderlichen booleschen Wert und eine optionale Zeichenfolgeeigenschaft verfügt.

' One required (positional) and one optional (named) parameter are applied.
<MyAttribute(false, OptionalParameter := "optional data")>
Public Class SomeClass
    '...
End Class

' One required (positional) parameter is applied.
<MyAttribute(false)>
Public Class SomeOtherClass
    '...
End Class
// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public class SomeClass
{
    //...
}
// One required (positional) parameter is applied.
[MyAttribute(false)]
public class SomeOtherClass
{
    //...
}
// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public ref class SomeClass
{
    //...
};
// One required (positional) parameter is applied.
[MyAttribute(false)]
public ref class SomeOtherClass
{
    //...
};

Deklarieren von Eigenschaften

Wenn Sie einen benannten Parameter definieren oder das Zurückgeben der vom Attribut gespeicherten Werte erleichtern möchten, deklarieren Sie eine Eigenschaft. Attributeigenschaften müssen als öffentliche Einheiten mit einer Beschreibung des zurückgegebenen Datentyps deklariert werden. Definieren Sie die Variable, die den Wert der Eigenschaft enthält, und ordnen Sie sie der Get-Methode und der Set-Methode zu. Das folgende Codebeispiel veranschaulicht die Implementierung einer einfachen Eigenschaft im Attribut.

Public Property MyProperty As Boolean
    Get
       Return Me.myvalue
    End Get
    Set
        Me.myvalue = Value
    End Set
End Property
public bool MyProperty
{
    get {return this.myvalue;}
    set {this.myvalue = value;}
}
property bool MyProperty
{
    bool get() {return this->myvalue;}
    void set(bool value) {this->myvalue = value;}
}

Beispiel für ein benutzerdefiniertes Attribut

In diesem Abschnitt werden die zuvor behandelten Informationen zusammengefasst. Es wird der Entwurf eines einfachen Attributs erläutert, das Informationen über den Autor eines Codeabschnitts dokumentiert. Das Attribut in diesem Beispiel speichert Namen und Qualifikation des Programmierers und gibt an, ob der Code überprüft wurde. Dabei werden drei private Variablen zum Aufnehmen der Werte verwendet, die gespeichert werden sollen. Jede Variable wird durch eine öffentliche Eigenschaft dargestellt, die die Werte abruft und festlegt. Schließlich wird der Konstruktor mit zwei erforderlichen Parametern definiert.

<AttributeUsage(AttributeTargets.All)>
Public Class DeveloperAttribute
    Inherits Attribute
    ' Private fields.
    Private myname As String
    Private mylevel As String
    Private myreviewed As Boolean

    ' This constructor defines two required parameters: name and level.

    Public Sub New(name As String, level As String)
        Me.myname = name
        Me.mylevel = level
        Me.myreviewed = False
    End Sub

    ' Define Name property.
    ' This is a read-only attribute.

    Public Overridable ReadOnly Property Name() As String
        Get
            Return myname
        End Get
    End Property

    ' Define Level property.
    ' This is a read-only attribute.

    Public Overridable ReadOnly Property Level() As String
        Get
            Return mylevel
        End Get
    End Property

    ' Define Reviewed property.
    ' This is a read/write attribute.

    Public Overridable Property Reviewed() As Boolean
        Get
            Return myreviewed
        End Get
        Set
            myreviewed = value
        End Set
    End Property
End Class
[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : Attribute
{
    // Private fields.
    private string name;
    private string level;
    private bool reviewed;

    // This constructor defines two required parameters: name and level.

    public DeveloperAttribute(string name, string level)
    {
        this.name = name;
        this.level = level;
        this.reviewed = false;
    }

    // Define Name property.
    // This is a read-only attribute.

    public virtual string Name
    {
        get {return name;}
    }

    // Define Level property.
    // This is a read-only attribute.

    public virtual string Level
    {
        get {return level;}
    }

    // Define Reviewed property.
    // This is a read/write attribute.

    public virtual bool Reviewed
    {
        get {return reviewed;}
        set {reviewed = value;}
    }
}
[AttributeUsage(AttributeTargets::All)]
public ref class DeveloperAttribute : Attribute
{
    // Private fields.
private:
    String^ name;
    String^ level;
    bool reviewed;

public:
    // This constructor defines two required parameters: name and level.

    DeveloperAttribute(String^ name, String^ level)
    {
        this->name = name;
        this->level = level;
        this->reviewed = false;
    }

    // Define Name property.
    // This is a read-only attribute.

    virtual property String^ Name
    {
        String^ get() {return name;}
    }

    // Define Level property.
    // This is a read-only attribute.

    virtual property String^ Level
    {
        String^ get() {return level;}
    }

    // Define Reviewed property.
    // This is a read/write attribute.

    virtual property bool Reviewed
    {
        bool get() {return reviewed;}
        void set(bool value) {reviewed = value;}
    }
};

Sie können dieses Attribut, wie folgt, unter Verwendung des vollständigen Namens DeveloperAttribute oder des abgekürzten Namens Developer anwenden.

<Developer("Joan Smith", "1")>

-or-

<Developer("Joan Smith", "1", Reviewed := true)>
[Developer("Joan Smith", "1")]

-or-

[Developer("Joan Smith", "1", Reviewed = true)]
[Developer("Joan Smith", "1")]

-or-

[Developer("Joan Smith", "1", Reviewed = true)]

Im ersten Beispiel wird die Anwendung des Attributs nur mit den erforderlichen benannten Parametern dargestellt, während im zweiten Beispiel die Anwendung des Attributs mit den erforderlichen und optionalen Parametern erläutert wird.

Siehe auch

Referenz

System.Attribute

AttributeUsageAttribute

Konzepte

Erweitern von Metadaten mithilfe von Attributen