Verfassen von benutzerdefinierten AttributenWriting Custom Attributes

Zum Entwerfen eigener, benutzerdefinierter Attribute brauchen Sie nicht viele neue Konzepte zu beherrschen.To design your own custom attributes, you do not need to master many new concepts. Wenn Sie mit objektorientierter Programmierung vertraut sind und wissen, wie Klassen entworfen werden, haben Sie bereits den größten Teil der Kenntnisse, die Sie benötigen.If you are familiar with object-oriented programming and know how to design classes, you already have most of the knowledge needed. Benutzerdefinierte Attribute sind im Wesentlichen traditionelle Klassen, die sich direkt oder indirekt aus System.Attributeableiten.Custom attributes are essentially traditional classes that derive directly or indirectly from System.Attribute. Genau wie traditionelle Klassen enthalten benutzerdefinierte Attribute Methoden zum Speichern und Abrufen von Daten.Just like traditional classes, custom attributes contain methods that store and retrieve data.

Die wichtigsten Schritte beim ordnungsgemäßen Entwerfen von benutzerdefinierten Attributklassen sind die folgenden:The primary steps to properly design custom attribute classes are as follows:

In diesem Abschnitt wird jeder dieser Schritte beschrieben, den Abschluss bildet ein Beispiel für ein benutzerdefiniertes Attribut.This section describes each of these steps and concludes with a custom attribute example.

Anwenden des AttributeUsage-AttributsApplying the AttributeUsageAttribute

Die Deklaration eines benutzerdefinierten Attributs beginnt mit dem System.AttributeUsageAttribute, das einige der Hauptmerkmale Ihrer Attributklasse definiert.A custom attribute declaration begins with the System.AttributeUsageAttribute, which defines some of the key characteristics of your attribute class. Sie können beispielsweise angeben, ob das Attribut von anderen Klassen geerbt werden kann, oder festlegen, auf welche Elemente das Attribut angewendet werden kann.For example, you can specify whether your attribute can be inherited by other classes or specify which elements the attribute can be applied to. Das folgende Codefragment zeigt die Verwendung des AttributeUsageAttribute.The following code fragment demonstrates how to use the AttributeUsageAttribute.

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

Die Klasse AttributeUsageAttribute weist drei Member auf, die für die Erstellung von benutzerdefinierten Attributen wichtig sind: AttributeTargets, Inherited und AllowMultiple.The AttributeUsageAttribute has three members that are important for the creation of custom attributes: AttributeTargets, Inherited, and AllowMultiple.

AttributeTargets-MemberAttributeTargets Member

Im vorherigen Beispiel wird AttributeTargets.All angegeben, was darauf hinweist, dass dieses Attribut auf alle Programmelemente angewendet werden kann.In the previous example, AttributeTargets.All is specified, indicating that this attribute can be applied to all program elements. Alternativ können Sie AttributeTargets.Class angeben und damit festlegen, dass Ihr Attribut nur auf eine Klasse angewendet werden kann, oder Sie können AttributeTargets.Method angeben, wodurch Sie festlegen, dass Ihr Attribut nur auf eine Methode angewendet werden kann.Alternatively, you can specify AttributeTargets.Class, indicating that your attribute can be applied only to a class, or AttributeTargets.Method, indicating that your attribute can be applied only to a method. Alle Programmelemente können in dieser Weise für die Beschreibung durch ein benutzerdefiniertes Attribut gekennzeichnet werden.All program elements can be marked for description by a custom attribute in this manner.

Sie können auch mehrere AttributeTargets-Werte übergeben.You can also pass multiple AttributeTargets values. Das folgende Codefragment gibt an, dass ein benutzerdefiniertes Attribut auf beliebige Klassen oder Methoden angewendet werden kann.The following code fragment specifies that a custom attribute can be applied to any class or method.

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

Inherited PropertyInherited Property

Die AttributeUsageAttribute.Inherited-Eigenschaft gibt an, ob das Attribut von Klassen geerbt werden kann, die von den Klassen abgeleitet werden, auf die das Attribut angewendet wird.The AttributeUsageAttribute.Inherited property indicates whether your attribute can be inherited by classes that are derived from the classes to which your attribute is applied. Diese Eigenschaft akzeptiert entweder das Flag true (den Standardwert) oder das Flag false.This property takes either a true (the default) or false flag. Im folgenden Beispiel weist MyAttribute für Inherited den Standardwert true auf, während YourAttribute einen Inherited-Wert von false hat.In the following example, MyAttribute has a default Inherited value of true, while YourAttribute has an Inherited value of false.

// This defaults to Inherited = true.
public ref class MyAttribute : Attribute
{
    //...
};

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

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

<AttributeUsage(AttributeTargets.Method, Inherited := False)>
Public Class YourAttribute
    Inherits Attribute
    '...
End Class

Die beiden Attribute werden dann auf eine Methode in der Basisklasse MyClassangewendet.The two attributes are then applied to a method in the base class MyClass.

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

Schließlich wird die Klasse YourClass von der Basisklasse MyClassgeerbt.Finally, the class YourClass is inherited from the base class MyClass. Die Methode MyMethod zeigt MyAttribute, aber nicht YourAttribute.The method MyMethod shows MyAttribute, but not YourAttribute.

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

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

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

End Class

AllowMultiple-EigenschaftAllowMultiple Property

Die AttributeUsageAttribute.AllowMultiple-Eigenschaft gibt an, ob mehrere Instanzen eines Attributs für ein Element vorhanden sein können.The AttributeUsageAttribute.AllowMultiple property indicates whether multiple instances of your attribute can exist on an element. Wenn sie auf true festgelegt ist, sind mehrere Instanzen zulässig; bei false (dem Standardwert) ist nur eine Instanz erlaubt.If set to true, multiple instances are allowed; if set to false (the default), only one instance is allowed.

Im folgenden Beispiel weist MyAttribute für AllowMultiple den Standardwert false auf, während YourAttribute den Wert true hat.In the following example, MyAttribute has a default AllowMultiple value of false, while YourAttribute has a value of true.

//This defaults to AllowMultiple = false.
public ref class MyAttribute : Attribute
{
};

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

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

<AttributeUsage(AttributeTargets.Method, AllowMultiple := true)>
Public Class YourAttribute
    Inherits Attribute
End Class

Wenn mehrere Instanzen dieser Attribute angewendet werden, führt MyAttribute zu einem Compilerfehler.When multiple instances of these attributes are applied, MyAttribute produces a compiler error. Das folgende Codebeispiel zeigt die gültige Verwendung von YourAttribute und die ungültige Verwaltung von MyAttribute.The following code example shows the valid use of YourAttribute and the invalid use of MyAttribute.

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

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    void YourMethod()
    {
        //...
    }
};
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 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

Wenn sowohl die AllowMultiple-Eigenschaft als auch die Inherited-Eigenschaft auf true festgelegt sind, kann eine Klasse, die von einer anderen Klasse geerbt wurde, ein Attribut erben, und zugleich kann in der gleichen untergeordneten Klasse eine weitere Instanz des gleichen Attributs angewendet werden.If both the AllowMultiple property and the Inherited property are set to true, a class that is inherited from another class can inherit an attribute and have another instance of the same attribute applied in the same child class. Wenn AllowMultiple auf false festgelegt ist, werden die Werte aller Attribute in der übergeordneten Klasse durch neue Instanzen der gleichen Attribute in der untergeordneten Klasse überschrieben.If AllowMultiple is set to false, the values of any attributes in the parent class will be overwritten by new instances of the same attribute in the child class.

Deklarieren der AttributklasseDeclaring the Attribute Class

Nach dem Anwenden von AttributeUsageAttributekönnen Sie beginnen, die Einzelheiten Ihres Attributs zu definieren.After you apply the AttributeUsageAttribute, you can begin to define the specifics of your attribute. Die Deklaration einer Attributklasse ähnelt der Deklaration einer traditionellen Klasse, wie im folgenden Code zu sehen.The declaration of an attribute class looks similar to the declaration of a traditional class, as demonstrated by the following code.

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

Diese Attibutdefinition veranschaulicht die folgenden Punkte:This attribute definition demonstrates the following points:

  • Attributklassen müssen als öffentliche Klassen deklariert werden.Attribute classes must be declared as public classes.

  • Gemäß Konvention endet der Name der Attributklasse mit dem Wort Attribute.By convention, the name of the attribute class ends with the word Attribute. Dies ist zwar nicht erforderlich, die Einhaltung dieser Konvention empfiehlt sich aber aus Gründen der besseren Übersicht.While not required, this convention is recommended for readability. Wenn das Attribut angewendet wird, ist die Aufnahme des Wortes „Attribute“ optional.When the attribute is applied, the inclusion of the word Attribute is optional.

  • Alle Attributklassen müssen direkt oder indirekt von System.Attribute erben.All attribute classes must inherit directly or indirectly from System.Attribute.

  • In Microsoft Visual Basic müssen alle benutzerdefinierten Attributklassen über das Attribut System.AttributeUsageAttribute verfügen.In Microsoft Visual Basic, all custom attribute classes must have the System.AttributeUsageAttribute attribute.

Deklarieren von KonstruktorenDeclaring Constructors

Attribute werden in der gleichen Weise wie traditionelle Klassen mit Konstruktoren initialisiert.Attributes are initialized with constructors in the same way as traditional classes. Das folgende Codefragment stellt ein Beispiel für einen typischen Attributkonstruktor dar.The following code fragment illustrates a typical attribute constructor. Dieser öffentliche Konstruktor akzeptiert einen Parameter und legt eine Membervariable auf seinen Wert fest.This public constructor takes a parameter and sets a member variable equal to its value.

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

Sie können den Konstruktor überladen, um verschiedene Kombinationen von Werten zu ermöglichen.You can overload the constructor to accommodate different combinations of values. Wenn Sie darüber hinaus eine Eigenschaft für Ihre benutzerdefinierte Attributklasse definieren, können Sie eine Kombination aus benannten und Positionsparametern zum Initialisieren des Attributs verwenden.If you also define a property for your custom attribute class, you can use a combination of named and positional parameters when initializing the attribute. Normalerweise definieren Sie alle erforderlichen Parameter als Positionsparameter und alle optionalen Parameter als benannt.Typically, you define all required parameters as positional and all optional parameters as named. In diesem Fall kann das Attribut nicht ohne den erforderlichen Parameter initialisiert werden.In this case, the attribute cannot be initialized without the required parameter. Alle anderen Parameter sind optional.All other parameters are optional. Beachten Sie, dass in Visual Basic die Konstruktoren für eine Attributklasse kein ParamArray-Argument verwenden sollten.Note that in Visual Basic, constructors for an attribute class should not use a ParamArray argument.

Das folgende Codebeispiel zeigt, wie ein Attribut, das den oben angegebenen Konstruktor verwendet, mithilfe von optionalen und erforderlichen Parametern angewendet werden kann.The following code example shows how an attribute that uses the previous constructor can be applied using optional and required parameters. Es wird angenommen, dass das Attribut einen erforderlichen Booleschen Wert und eine optionale Zeichenfolgeneigenschaft aufweist.It assumes that the attribute has one required Boolean value and one optional string property.

// 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
{
    //...
};
// 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 Class SomeClass
    '...
End Class

' One required (positional) parameter is applied.
<MyAttribute(false)>
Public Class SomeOtherClass
    '...
End Class

Deklarieren von EigenschaftenDeclaring Properties

Wenn Sie einen benannten Parameter definieren oder eine einfache Möglichkeit zum Zurückgeben der von Ihrem Attribut gespeicherten Werte bereitstellen möchten, deklarieren Sie eine Eigenschaft.If you want to define a named parameter or provide an easy way to return the values stored by your attribute, declare a property. Attributeigenschaften müssen als öffentliche Entitäten mit einer Beschreibung des zurückgegebenen Datentyps deklariert werden.Attribute properties should be declared as public entities with a description of the data type that will be returned. Definieren Sie die Variable, die den Wert der Eigenschaft enthalten soll, und ordnen Sie sie den Methoden get und set zu.Define the variable that will hold the value of your property and associate it with the get and set methods. Das folgende Codebeispiel veranschaulicht, wie eine einfache Eigenschaft in Ihrem Attribut implementiert wird.The following code example demonstrates how to implement a simple property in your attribute.

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

Beispiel für ein benutzerdefiniertes AttributCustom Attribute Example

Dieser Abschnitt beinhaltet die Informationen aus den vorhergehenden Abschnitten und zeigt das Entwerfen eines einfachen Attributs, das Informationen über den Autor eines Codeabschnitts dokumentiert.This section incorporates the previous information and shows how to design a simple attribute that documents information about the author of a section of code. Das Attribut in diesem Beispiel speichert den Namen und die Qualifikation des Programmierers und gibt an, ob der Code überprüft wurde.The attribute in this example stores the name and level of the programmer, and whether the code has been reviewed. Es verwendet drei private Variablen zum Speichern der eigentlichen, zu speichernden Werte.It uses three private variables to store the actual values to save. Jede Variable wird durch eine öffentliche Eigenschaft dargestellt, die zum Abrufen und Festlegen der Werte verwendet wird.Each variable is represented by a public property that gets and sets the values. Schließlich wird der Konstruktor mit zwei erforderlichen Parametern definiert.Finally, the constructor is defined with two required parameters.

[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;}
    }
};
[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 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

Sie können das Attribut mit seinem vollständigen Namen DeveloperAttributeoder mit seinem abgekürzten Namen Developerauf eine der folgenden Weisen anwenden.You can apply this attribute using the full name, DeveloperAttribute, or using the abbreviated name, Developer, in one of the following ways.

[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 das Attribut nur mit den erforderlichen benannten Parametern angewendet, während das zweite Beispiel die Anwendung des Attributs mit den erforderlichen und den optionalen Parametern zeigt.The first example shows the attribute applied with only the required named parameters, while the second example shows the attribute applied with both the required and optional parameters.

Siehe auchSee also