Delen via


Aangepaste kenmerken schrijven

Als u aangepaste kenmerken wilt ontwerpen, hoeft u niet veel nieuwe concepten te leren. Als u bekend bent met objectgeoriënteerde programmering en weet hoe u klassen ontwerpt, hebt u al de meeste kennis nodig. Aangepaste kenmerken zijn traditionele klassen die rechtstreeks of indirect zijn afgeleid van de System.Attribute klasse. Net als bij traditionele klassen bevatten aangepaste kenmerken methoden waarmee gegevens worden opgeslagen en opgehaald.

De primaire stappen voor het correct ontwerpen van aangepaste kenmerkklassen zijn als volgt:

In deze sectie wordt elk van deze stappen beschreven en wordt afgesloten met een voorbeeld van een aangepast kenmerk.

De AttributeUsageAttribute toepassen

Een aangepaste kenmerkdeclaratie begint met het System.AttributeUsageAttribute kenmerk, waarmee enkele van de belangrijkste kenmerken van uw kenmerkklasse worden gedefinieerd. U kunt bijvoorbeeld opgeven of uw kenmerk kan worden overgenomen door andere klassen of op welke elementen het kenmerk kan worden toegepast. Het volgende codefragment laat zien hoe u het AttributeUsageAttributevolgende gebruikt:

[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

De AttributeUsageAttribute groep bevat drie leden die belangrijk zijn voor het maken van aangepaste kenmerken: AttributeTargets, Overgenomen en AllowMultiple.

AttributeTargets Member

In het voorgaande voorbeeld AttributeTargets.All wordt opgegeven, waarmee wordt aangegeven dat dit kenmerk kan worden toegepast op alle programma-elementen. U kunt ook opgeven AttributeTargets.Class, waarmee wordt aangegeven dat uw kenmerk alleen op een klasse kan worden toegepast of AttributeTargets.Methoddat uw kenmerk alleen op een methode kan worden toegepast. Alle programma-elementen kunnen op deze manier worden gemarkeerd voor beschrijving door een aangepast kenmerk.

U kunt ook meerdere AttributeTargets waarden doorgeven. Het volgende codefragment geeft aan dat een aangepast kenmerk kan worden toegepast op elke klasse of methode:

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

Overgenomen eigenschap

De AttributeUsageAttribute.Inherited eigenschap geeft aan of uw kenmerk kan worden overgenomen door klassen die zijn afgeleid van de klassen waarop uw kenmerk wordt toegepast. Deze eigenschap heeft een true (de standaard) of false vlag. In het volgende voorbeeld MyAttribute heeft u een standaardwaarde Inherited van true, terwijl YourAttribute deze een Inherited waarde heeft van 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

De twee kenmerken worden vervolgens toegepast op een methode in de basisklasse 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

Ten slotte wordt de klasse YourClass overgenomen van de basisklasse MyClass. De methode MyMethod toont MyAttribute maar niet 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

Eigenschap AllowMultiple

De AttributeUsageAttribute.AllowMultiple eigenschap geeft aan of er meerdere exemplaren van uw kenmerk kunnen bestaan op een element. Als dit is ingesteld op true, zijn meerdere exemplaren toegestaan. Als deze optie is ingesteld op false (de standaardinstelling), is slechts één exemplaar toegestaan.

In het volgende voorbeeld MyAttribute heeft u een standaardwaarde AllowMultiple van false, terwijl YourAttribute deze een waarde heeft van 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

Wanneer meerdere exemplaren van deze kenmerken worden toegepast, MyAttribute wordt er een compilerfout gegenereerd. In het volgende codevoorbeeld ziet u het geldige gebruik van YourAttribute en het ongeldige gebruik van 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

Als zowel de AllowMultiple eigenschap als de Inherited eigenschap zijn ingesteld op true, kan een klasse die wordt overgenomen van een andere klasse een kenmerk overnemen en een ander exemplaar van hetzelfde kenmerk toepassen in dezelfde onderliggende klasse. Als AllowMultiple deze optie is ingesteld false, worden de waarden van kenmerken in de bovenliggende klasse overschreven door nieuwe exemplaren van hetzelfde kenmerk in de onderliggende klasse.

De kenmerkklasse declareren

Nadat u het AttributeUsageAttributekenmerk hebt toegepast, begint u met het definiëren van de specifieke kenmerken van uw kenmerk. De declaratie van een kenmerkklasse lijkt op de declaratie van een traditionele klasse, zoals wordt gedemonstreerd door de volgende 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

Deze kenmerkdefinitie demonstreert de volgende punten:

  • Kenmerkklassen moeten worden gedeclareerd als openbare klassen.

  • Volgens de conventie eindigt de naam van de kenmerkklasse met het woord Kenmerk. Hoewel dit niet vereist is, wordt deze conventie aanbevolen voor leesbaarheid. Wanneer het kenmerk wordt toegepast, is de opname van het woord Kenmerk optioneel.

  • Alle kenmerkklassen moeten direct of indirect worden overgenomen van de System.Attribute klasse.

  • In Microsoft Visual Basic moeten alle aangepaste kenmerkklassen het System.AttributeUsageAttribute kenmerk hebben.

Constructors declareren

Net als bij traditionele klassen worden kenmerken geïnitialiseerd met constructors. Het volgende codefragment illustreert een typische kenmerkconstructor. Deze openbare constructor neemt een parameter en stelt een lidvariabele in die gelijk is aan de bijbehorende waarde.

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

U kunt de constructor overbelasten voor verschillende combinaties van waarden. Als u ook een eigenschap definieert voor uw aangepaste kenmerkklasse, kunt u een combinatie van benoemde en positionele parameters gebruiken bij het initialiseren van het kenmerk. Normaal gesproken definieert u alle vereiste parameters als positionele en alle optionele parameters als benoemd. In dit geval kan het kenmerk niet worden geïnitialiseerd zonder de vereiste parameter. Alle andere parameters zijn optioneel.

Notitie

In Visual Basic mogen constructors voor een kenmerkklasse geen argument gebruiken ParamArray .

In het volgende codevoorbeeld ziet u hoe een kenmerk dat gebruikmaakt van de vorige constructor kan worden toegepast met optionele en vereiste parameters. Hierbij wordt ervan uitgegaan dat het kenmerk één vereiste Booleaanse waarde en één optionele tekenreekseigenschap heeft.

// 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

Eigenschappen declareren

Als u een benoemde parameter wilt definiëren of een eenvoudige manier wilt bieden om de waarden te retourneren die zijn opgeslagen door uw kenmerk, declareert u een eigenschap. Kenmerkeigenschappen moeten worden gedeclareerd als openbare entiteiten met een beschrijving van het gegevenstype dat wordt geretourneerd. Definieer de variabele die de waarde van uw eigenschap bevat en koppel deze aan de get en set methoden. In het volgende codevoorbeeld ziet u hoe u een eigenschap in uw kenmerk implementeert:

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

Voorbeeld van aangepast kenmerk

Deze sectie bevat de vorige informatie en laat zien hoe u een kenmerk ontwerpt dat informatie over de auteur van een codesectie documenteert. Het kenmerk in dit voorbeeld slaat de naam en het niveau van de programmeur op en of de code is gecontroleerd. Er worden drie privévariabelen gebruikt om de werkelijke waarden op te slaan om op te slaan. Elke variabele wordt vertegenwoordigd door een openbare eigenschap waarmee de waarden worden opgehaald en ingesteld. Ten slotte wordt de constructor gedefinieerd met twee vereiste 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

U kunt dit kenmerk op een van de volgende manieren toepassen met behulp van de volledige naam, DeveloperAttributeof met behulp van de verkorte naam Developer:

[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)>

In het eerste voorbeeld ziet u het kenmerk dat wordt toegepast met alleen de vereiste benoemde parameters. In het tweede voorbeeld ziet u het kenmerk dat is toegepast met zowel de vereiste als optionele parameters.

Zie ook