9.2. Defining a Custom Attribute An attribute is merely a class that inherits from System.Attribute. This section shows you how to build a custom attribute called <DeveloperNote>, which allows a developer to add assorted information (the developer's name, the development date, a comment, and whether the code was written in response to a bug) to a block of code. Define a public class that inherits from System.Attribute or from another attribute class derived from System.Attribute. Public Class DeveloperNoteAttribute Inherits System.Attribute By convention, the name of the class ends with the substring "Attribute." Apply the <AttributeUsage> attribute to the class, which defines the language elements to which the custom attribute can be applied. The attribute's only required argument is one of the following members of the AttributeTargets enumeration: - AttributeTargets.All
- AttributeTargets.Assembly
- AttributeTargets.Class
- AttributeTargets.Constructor
- AttributeTargets.Delegate
- AttributeTargets.Enum
- AttributeTargets.Event
- AttributeTargets.Field
- AttributeTargets.GenericParameter
- AttributeTargets.Interface
- AttributeTargets.Method
- AttributeTargets.Module
- AttributeTargets.Parameter
- AttributeTargets.Property
- AttributeTargets.ReturnValue
- AttributeTargets.Struct
If an attribute applies to multiple programming elements, but not all elements, the relevant enumeration values can be Or'd together. Since the <DeveloperNote> attribute is pretty generic, it will be applicable to All program elements. <AttributeUsage(AttributeTargets.All, _ Inherited:=True, _ AllowMultiple:=True)> _ Public Class DeveloperNoteAttribute Inherits System.Attribute The Inherited argument (set to true) allows new attribute classes to be derived from DeveloperNoteAttribute. The AllowMultiple argument (set to TRue) allows the attribute to be applied to the same program element multiple times. Add some protected class members to hold the custom values, like the developer name. Protected developerName As String Protected codeComment As String Protected codeRecordDate As Date Protected dueToBug As Boolean Create the class constructor (the New routine), which is called when the attribute is applied to a particular language element. The class constructor defines the attribute's required or positional arguments. At a minimum, the developer using this attribute must to record his or her name, a comment, and a date. Public Sub New(Name As String, Comment As String, _ DateRecorded As String) ' ----- Store the commentary for this program element. MyBase.New( ) developerName = Name codeComment = Comment codeRecordDate = CDate(DateRecorded) End Sub The DateRecorded parameter comes into the constructor as a String, not as a Date. Only certain data types can be used as attribute parameters: integral data types (Byte, Short, Integer, Long), floating point data types (Single and Double), Char, String, Boolean, an enumerated type, or System.Type. Other data types, including Date, Decimal, Object, and structured types, cannot be used as parameters. The new VB 2005 integral data types (SByte, UShort, UInteger, and ULong) cannot be used, because only Common Language Specification (CLS) compliant data types can be used in attribute definitions, and these new types do not meet that requirement. Declare properties and fields. The attribute's public properties and fields correspond to parameters required by the class constructor and to optional parameters supplied when the attribute is applied to a language element. The <DeveloperNote> attribute needs a property for each of the three required constructor arguments, plus one for the optional Bug property. Public Property Name( ) As String Get Return developerName End Get Set(ByVal value As String) developerName = value End Set End Property Public Property Comment( ) As String Get Return codeComment End Get Set(ByVal value As String) codeComment = value End Set End Property Public Property DateRecorded( ) As Date Get Return codeRecordDate End Get Set(ByVal value As Date) codeRecordDate = value End Set End Property Public Property Bug( ) As Boolean Get Return dueToBug End Get Set(ByVal value As Boolean) dueToBug = value End Set End Property That's the whole attribute class with only the most basic of features. The .NET Framework takes care of everything else, including the recording of each custom attribute value in the assembly's metadata. The complete code for the attribute class appears in Example 9-1. Example 9-1. The DeveloperNoteAttribute attribute class Option Strict On Imports System Namespace Extensions.CustomAttributes <AttributeUsage(AttributeTargets.All, _ Inherited:=True, _ AllowMultiple:=True)> _ Public Class DeveloperNoteAttribute Inherits System.Attribute Protected developerName As String Protected codeComment As String Protected codeRecordDate As Date Protected dueToBug As Boolean Public Sub New(Name As String, Comment As String, _ DateRecorded As String) ' ----- Store the commentary for this program element. MyBase.New( ) developerName = Name codeComment = Comment codeRecordDate = CDate(DateRecorded) End Sub Public Property Name( ) As String Get Return developerName End Get Set(ByVal value As String) developerName = value End Set End Property Public Property Comment( ) As String Get Return codeComment End Get Set(ByVal value As String) codeComment = value End Set End Property Public Property DateRecorded( ) As Date Get Return codeRecordDate End Get Set(ByVal value As Date) codeRecordDate = value End Set End Property Public Property Bug( ) As Boolean Get Return dueToBug End Get Set(ByVal value As Boolean) dueToBug = value End Set End Property End Class End Namespace |
|