- Creating the Attribute Project
- Applying the AttributeUsageAttribute
- Inheriting from System.Attribute
- Defining a Constructor and Positional Arguments
- Defining Named Arguments
- Testing the Attribute
- Summary
Defining a Constructor and Positional Arguments
As the custom attribute evolves, we have to decide which information to get from the user, and where we can supply reasonable default values. We can change these choices later, if necessary, so for now let's require only one argument. We need the user to express the complete assembly-qualified name of the control that the designer should generate. This is expressed in the constructor. Listing 4 further updates the custom attribute, demonstrating how to define the constructor, positional arguments, and related fields and properties. (I added line numbers for reference here.)
NOTE
An assembly-qualified name is the string name of a class, including the complete namespace, version, language, culture information, and public key token. .NET needs this information to know which specific class you're referencing.
We could modify the custom attribute to use a Type record. The Type information might be easier to supply in an actual application.
Listing 4Adding a Constructor and Supporting Members
1: <AttributeUsage(AttributeTargets.Property, _ 2: Inherited:=True, AllowMultiple:=True)> _ 3: Public Class ControlDesignerAttribute 4: Inherits System.Attribute 5: 6: Private FControlName As String 7: Public Sub New(ByVal ControlName As String) 8: FControlName = ControlName 9: End Sub 10: 11: Public ReadOnly Property ControlName() As String 12: Get 13: Return FControlName 14: End Get 15: End Property 16: End Class
NOTE
Microsoft is moving away from the Hungarian specific typed-prefix notation. Typed prefix notations were invented for weakly typed languages such as C. Fortunately, Visual Basic .NET is strongly typed, making specific prefixes unnecessary.
However, because Visual Basic .NET isn't case sensitive, we need a reliable way to distinguish easily between fields and properties. I borrowed from Delphi's convention to simply use F for field and drop the F for the related property. I find this approach refreshingly easy. You're welcome to use any convention with the reminder to be consistent.
Line 6 defines the field to store the control name, FControlName. The named argument is a string named ControlName. After the attribute is created, the application generator needs to read but not modify this value, so I made ControlName a read-only property.