homelinksBlijf op de hoogte van de recente aanpassingen op vbvoorbeelden!
Visual Basic 2010 Voorbeelden

visual basic 2010 broncode voorbeelden

Microsoft Visual Studio 2010Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

25.2. Zelf Attributen Definiëren

Print Email Deel op Facebook Deel op Twitter

Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

Attributen kunnen ook zelf gedefinieerd worden.  Dit is een vrij eenvoudig werkje, je maakt een eigen attribuutklasse die je doet overerven van de Attribute klasse.   Deze attribuutklasse kan dan gebruikt worden om metadata aan een definitie toe te voegen.

Het is voor de leesbaarheid aan te raden de "Attribute" suffix te gebruiken in de identifier van de attribuutklasse.

Bij de definitie van die klasse plaats je een AttributeUsage attribuut, daar geef je als argumentwaarde een AttributeTargets enumeratiewaarde aan de constructor door om op te geven op welke entiteit de attribuut slaat.
Mogelijkheden zijn : All, Assembly, Class, Constructor, Delegate, Enum, Event, Field, Interface, Method, Module, Parameter, Property, ReturnValue en Struct.  Het zou ook mogelijk zijn om AttributeTargets.Constructor Or AttributeTargets.Method Or AttributeTargets.Property in te stellen.  Dit zou dus bruikbaar zijn om aan te geven dat het attribuut van toepassing kan zijn op de entiteiten constructor, method en/of property.

Het AttributeUsage attribute is dus bruikbaar om bij het definiëren van een attribuutklasse aan te geven waarop het attribuut dat je aan het definiëren bent van toepassing zal zijn.

De volgende argumentwaarden die hier in de voorbeelden lijken doorgegeven te worden aan de constructor van de AttributeUsage klasse zijn eigenlijk geen argumentwaarden.  Ze zijn gewoon een verkorte taalconstructie ( met een toekenning via de operator := ) om hier meteen na het instantiëren van dat attribuut de eigenschappen AllowMultiple en Inherited van de AttributeUsage klasse op een bepaalde waarde in te stellen.

AllowMultiple kan je op True instellen als het attribuut dat je aan het definiëren bent meerder keren kan gebruikt worden op de entiteit(en) die ervoor is/zijn opgegeven.  By default kan een attribuut maar één keer worden toegepast.

Inherited kan je op False instellen als je wenst dat het attribuut dat je aan het definiëren bent niet zal worden overgeërfd naar subklassen van de klasse waarbij dat attribuut zal gedefinieerd worden.  By default worden attributen overgeërfd.

Bij het definiëren van de constructor van een attribuutklasse ben je beperkt in de mogelijke datatypes voor de parameters van die constructor, namelijk : Byte, Short, Integer, Long, Single, Double, Char, String, Boolean, Type of eender welk enumeratietype.  Dit omdat enkele deze geserialiseerd kunnen worden in de metadata voor de assembly.

Via reflection kan de aan de klasse of aan de members toegevoegde metadata vervolgens weer worden opgespoord en vervolgens op de één of andere manier gebruik van worden gemaakt.
Het opsporen van attributen kan bijvoorbeeld via de classmembers GetCustomAttribute en GetCustomAttributes methods van de Attribute klasse.
Visual Basic 2010 Broncode
<AttributeUsage(AttributeTargets.Class, AllowMultiple:=True, Inherited:=False)> _
Public Class HistoryAttribute : Inherits Attribute : Implements IComparable
    Public m_Date As String
    Public Property [Date]() As String
        Get
            [Date] = m_Date
        End Get
        Set(ByVal value As String)
            m_Date = value
        End Set
    End Property
    Private m_Author As String
    Public Property Author() As String
        Get
            Author = m_Author
        End Get
        Set(ByVal value As String)
            m_Author = value
        End Set
    End Property
    Private m_Change As String
    Public Property Change() As String
        Get
            Change = m_Change
        End Get
        Set(ByVal value As String)
            m_Change = value
        End Set
    End Property
    Public Sub New(ByVal [date] As String, _
                   ByVal author As String, ByVal change As String)
        Me.Date = [date]
        Me.Author = author
        Me.Change = change
    End Sub
    Public Function CompareTo(ByVal obj As Object) As Integer _
                                         Implements System.IComparable.CompareTo
        If TypeOf obj Is HistoryAttribute Then
            Dim ha As HistoryAttribute = DirectCast(obj, HistoryAttribute)
            Return [Date].CompareTo(ha.Date)
        End If
    End Function
End Class
Public Class ClassInfo
    Public Shared Function GetHistory(ByVal type As Type) As String
        Dim historyAttributes As HistoryAttribute() = _
          DirectCast(Attribute.GetCustomAttributes(type, GetType(HistoryAttribute)),  _
                     HistoryAttribute())
        GetHistory &= "fullname : " & type.FullName & _
                      Environment.NewLine() & Environment.NewLine() & _
                      "history  : " & Environment.NewLine()
        Array.Sort(historyAttributes)
        For Each historyAttribute As HistoryAttribute In historyAttributes
            GetHistory &= "  date   : " & historyAttribute.Date.ToString() & " - " & _
                          "author : " & historyAttribute.Author & _
                          Environment.NewLine() & _
                          "  change : " & historyAttribute.Change & _
                          Environment.NewLine() & Environment.NewLine()
        Next
    End Function
End Class
<History("2008-02-21", "John", "Created this class."), _
History("2008-02-22", "Jane", "Added Method1."), _
History("2008-02-23", "John", "Corrected Method1."), _
History("2008-02-24", "Paul", "Added Method2.")> _
Class Class1
    Public Sub Method1()
        Console.WriteLine("method1")
    End Sub
    Public Sub Method2()
        Console.WriteLine("method2")
    End Sub
End Class
Class Example1
    Public Shared Sub Main()
        Console.WriteLine(ClassInfo.GetHistory(GetType(Class1)))
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
fullname : ContentConsoleApplication.Class1

history  :
  date   : 2008-02-21 - author : John
  change : Created this class.

  date   : 2008-02-22 - author : Jane
  change : Added Method1.

  date   : 2008-02-23 - author : John
  change : Corrected Method1.

  date   : 2008-02-24 - author : Paul
  change : Added Method2.
Een ander voorbeeld :
Visual Basic 2010 Broncode
Public Class ContractAttribute : Inherits Attribute
    Private ReadOnly m_Text As String
    Public ReadOnly Property Text() As String
        Get
            Text = m_Text
        End Get
    End Property
    Public Sub New(ByVal text As String)
        m_Text = text
    End Sub
End Class
<AttributeUsage(AttributeTargets.All, AllowMultiple:=False, Inherited:=False)> _
Public Class SummaryAttribute : Inherits ContractAttribute
    Public Sub New(ByVal text As String)
        MyBase.New(text)
    End Sub
End Class
<AttributeUsage(AttributeTargets.Class, AllowMultiple:=True, Inherited:=True)> _
Public Class InvariantAttribute : Inherits ContractAttribute
    Public Sub New(ByVal text As String)
        MyBase.New(text)
    End Sub
End Class
<AttributeUsage(AttributeTargets.Constructor Or AttributeTargets.Method Or _
                AttributeTargets.Property, _
                AllowMultiple:=True, Inherited:=False)> _
Public Class PreConditionAttribute : Inherits ContractAttribute
    Public Sub New(ByVal text As String)
        MyBase.New(text)
    End Sub
End Class
<AttributeUsage(AttributeTargets.Constructor Or AttributeTargets.Method Or _
                AttributeTargets.Property, _
                AllowMultiple:=True, Inherited:=False)> _
Public Class PostConditionAttribute : Inherits ContractAttribute
    Public Sub New(ByVal text As String)
        MyBase.New(text)
    End Sub
End Class
Partial Class ClassInfo
    Public Shared Function GetContract(ByVal type As Type) As String
        Dim summaryAttribute As SummaryAttribute = _
          DirectCast(Attribute.GetCustomAttribute(type, GetType(SummaryAttribute)),  _
                     SummaryAttribute)
        Dim invariantAttributes As InvariantAttribute() = _
          DirectCast(Attribute.GetCustomAttributes(type, GetType(InvariantAttribute)),  _
                     InvariantAttribute())
        GetContract &= "fullname : " & type.FullName & Environment.NewLine() & _
                       "   invariants : " & Environment.NewLine()
        For Each invariantAttribute As InvariantAttribute In invariantAttributes
            GetContract &= "      - " & invariantAttribute.Text & Environment.NewLine()
        Next
        Dim membersInfo As Reflection.MemberInfo() = type.GetMembers()
        For Each memberInfo As Reflection.MemberInfo In membersInfo
            If (memberInfo.MemberType = Reflection.MemberTypes.Method OrElse _
                memberInfo.MemberType = Reflection.MemberTypes.Property OrElse _
                memberInfo.MemberType = Reflection.MemberTypes.Constructor) AndAlso _
                memberInfo.DeclaringType Is type Then
                GetContract &= GetContract(memberInfo)
            End If
        Next
    End Function
    Public Shared Function GetContract(ByVal member As Reflection.MemberInfo) As String
        GetContract &= "   " & member.Name & " : " & Environment.NewLine()
        Dim summary As SummaryAttribute() = _
          DirectCast(member.GetCustomAttributes(GetType(SummaryAttribute), False),  _
                     SummaryAttribute())
        GetContract &= "      summary        : "
        Dim summaryText As String = "-"
        If summary.Length > 0 Then
            summaryText = summary(0).Text
        End If
        GetContract &= summaryText & Environment.NewLine()
        Dim preConditions As PreConditionAttribute() = _
          DirectCast(member.GetCustomAttributes(GetType(PreConditionAttribute), False),  _
                    PreConditionAttribute())
        GetContract &= "      pre-condities  : "
        Dim preConditionText As String
        For Each preCondition As PreConditionAttribute In preConditions
            preConditionText &= Environment.NewLine() & _
                                "                       - " & preCondition.Text
        Next
        If preConditionText = "" Then
            GetContract &= "-" & Environment.NewLine()
        Else
            GetContract &= preConditionText & Environment.NewLine()
        End If
        Dim postConditions As PostConditionAttribute() = _
          DirectCast(member.GetCustomAttributes(GetType(PostConditionAttribute), False),  _
                    PostConditionAttribute())
        GetContract &= "      post-condities : "
        Dim postConditionText As String
        For Each postCondition As PostConditionAttribute In postConditions
            postConditionText &= Environment.NewLine() & _
                                "                       - " & postCondition.Text
        Next
        If postConditionText = "" Then
            GetContract &= "-" & Environment.NewLine()
        Else
            GetContract &= postConditionText & Environment.NewLine()
        End If
    End Function
End Class
Class Assertion
    Public Shared Sub Require(ByVal condition As Boolean)
        If Not condition Then Throw New PreConditionException
    End Sub
    Public Shared Sub Ensure(ByVal condition As Boolean)
        If Not condition Then Throw New PostConditionException
    End Sub
    Public Class PreConditionException : Inherits ApplicationException
    End Class
    Public Class PostConditionException : Inherits ApplicationException
    End Class
End Class
<Summary("Bounded LIFO collection."), _
Invariant("GetCount() >= 0"), _
Invariant("GetSize() >= 2")> _
Class BoundedStack
    Private m_Stack As Object()
    Private m_Size As Integer
    Private m_Count As Integer
    <Summary("Constructor expects capacity ( size )."), _
     PreCondition("size > 1"), _
     PostCondition("GetSize() = size")> _
    Public Sub New(ByVal size As Integer)
        Assertion.Require(size > 1)
        m_Size = size
        ReDim m_Stack(m_Size - 1)
        Assertion.Ensure(getSizeQuery() = size AndAlso getCountQuery() = 0)
        Assertion.Ensure(invariant())
    End Sub
    <Summary("GetSize() gets the capacity."), _
     PostCondition("GetSize() > 1")> _
    Public Function GetSize() As Integer
        GetSize = getSizeQuery()
        Assertion.Ensure(GetSize > 1)
        Assertion.Ensure(invariant())
    End Function
    Private Function getSizeQuery() As Integer
        getSizeQuery = m_Size
    End Function
    <Summary("GetCount() gets the count."), _
     PostCondition("GetCount() >= 0"), _
     PostCondition("GetCount() <= GetSize()")> _
    Public Function GetCount() As Integer
        GetCount = getCountQuery()
        Assertion.Ensure(GetCount >= 0 AndAlso GetCount <= getSizeQuery())
        Assertion.Ensure(invariant())
    End Function
    Private Function getCountQuery() As Integer
        getCountQuery = m_Count
    End Function
    '
    Private Function invariant() As Boolean
        Return getCountQuery() >= 0 AndAlso getSizeQuery() >= 2
    End Function
    ' ...
End Class
Public Class Example2
    Public Shared Sub Main()
        Console.WriteLine(ClassInfo.GetContract(GetType(BoundedStack)))
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
fullname : ContentConsoleApplication.BoundedStack
invariants :
   - GetCount() >= 0
   - GetSize() >= 2
GetSize :
   summary        : GetSize() gets the capacity.
   pre-condities  : -
   post-condities :
                    - GetSize() > 1
GetCount :
   summary        : GetCount() gets the count.
   pre-condities  : -
   post-condities :
                    - GetCount() >= 0
                    - GetCount() <= GetSize()
.ctor :
   summary        : Constructor expects capacity ( size ).
   pre-condities  :
                    - size > 1
   post-condities :
                    - GetSize() = size

Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.