Listing 1

<WebMethod( _
  CacheDuration:=30, _
  MessageName:="SayHello")> _
Public Function HelloWorld() As String
  Return "Hello World"
End Function

Listing 2

<Serializable()> _
Public Class Employee
  <NonSerialized()> Public FirstName As String
  Public LastName As String
End Class

Listing 3

<AttributeUsage(AttributeTargets.Class)> _
Public Class DataClassAttribute
  Inherits System.Attribute

  Public IsConfigurable As Boolean = False
  Public Label As String = String.Empty
  Public GetMethod As String = "Get"
  Public InsertMethod As String = "Insert"
  Public UpdateMethod As String = "Update"
  Public DeleteMethod As String = "Delete"
End Class

Listing 4

<DataClass( _
  DeleteMethod:="Delete", _
  GetMethod:="Get", _
  InsertMethod:="Insert", _
  IsConfigurable:=True, _
  Label:="Employee", _
  UpdateMethod:="Update")> _
Public Class Employee
  Public FirstName As String
  Public LastName As String

  Public Sub Delete(ByVal ID As Long)
  End Sub

  Public Sub Get(ByVal ID As Long)
  End Sub

  Public Sub Insert(FirstName as string, _
                    LastName as string)
  End Sub

  Public Sub Update(ByVal ID As Long _
                    FirstName as string, _
                    LastName as string)
  End Sub
End Class

Listing 5

<AttributeUsage(AttributeTargets.Property)> _
Public Class ConfigurationAttribute
  Inherits System.Attribute

  Public IsConfigurable As Boolean = False
  Public Label As String = String.Empty
  Public Description As String = String.Empty
  Public Minimum As String = "0"
  Public Maximum As String = "0"
  Public ValidationExpression As String = ""
  Public ControlType As String = "TextBox"
End Class

Listing 6

<DataClass( _
  DeleteMethod:="Delete", _
  GetMethod:="Get", _
  InsertMethod:="Insert", _
  IsConfigurable:=True, _
  Label:="Employee", _
  UpdateMethod:="Update")> _
Public Class Employee
  <Configuration( _
    ControlType:="TextBox", _
    Description:="Enter the Employee's First Name", _
    IsConfigurable:=True, _
    Label:="First Name", _
    Maximum:="20", _
    Minimum:="0", _
    ValidationExpression:="\w*")> _
  Public Property FirstName() As String
  End Property

  <Configuration( _
    ControlType:="TextBox", _
    Description:="Enter the Employee's Last Name", _
    IsConfigurable:=True, _
    Label:="Last Name", _
    Maximum:="20", _
    Minimum:="0", _
    ValidationExpression:="\w*")> _
  Public Property LastName() As String
  End Property
End Class

Listing 7

Public Class ConfigurationInfo
  Inherits ConfigurationAttribute

  Public Type As Type
  Public Name As String
End Class

Public Function GetPropertyConfigurationData() _
                As HybridDictionary
  Dim ca As ConfigurationAttribute
  Dim ci As ConfigurationInfo
  Dim PropertyList() As PropertyInfo
  Dim ReturnValue As New HybridDictionary

  ' Obtain a list of explicitly-declared, 
  ' public properties
  PropertyList = Me.GetType().GetProperties( _
                   BindingFlags.Public Or _
                   BindingFlags.Instance Or 
                   BindingFlags.DeclaredOnly)

  ' Process each property
  For Each pi As PropertyInfo In PropertyList
    ' Obtain a list of all attributes attached
    ' to this property, but filter the list so
    ' that it includes only our 
    ' ConfigurationAttribute.
    Dim Attributes() As Object = _
          pi.GetCustomAttributes( _
              GetType(ConfigurationAttribute), _
              False)

    ' check to see if the attribute was found
    If Attributes.Length > 0 Then
      ' Obtain a reference to the attribute
      ca = CType(Attributes(0), _
                 ConfigurationAttribute)

      If Not ca Is Nothing Then
        ' The attribute exists.  Create and 
        ' populate a ConfigurationInfo object 
        ' using data from the attribute and
        ' the property itself
        ci = New ConfigurationInfo

        With ci
          .ControlType = ca.ControlType
          .Description = ca.Description
          .IsConfigurable = ca.IsConfigurable
          .Label = ca.Label
          .Maximum = ca.Maximum
          .Minimum = ca.Minimum
          .Name = pi.Name
          .Type = pi.PropertyType
          .ValidationExpression = _
                ca.ValidationExpression

          ReturnValue.Add(ci.Name, ci)
        End With
      End If
    End If
  Next

  Return ReturnValue
End Function

Public Function GetClassConfigurationData() _
                   As DataClassAttribute
  Dim dca As DataClassAttribute = Nothing

  ' Obtain a list of all attributes attached
  ' to this object, but filter the list so
  ' that it includes only our 
  ' DataClassAttribute.
  Dim Attributes() As Object = _
        Me.GetType().GetCustomAttributes( _
            GetType(DataClassAttribute), _
            False)

  If Attributes.Length > 0 Then
    ' The attribute exists.  Return the 
    ' DataClassAttribute
    dca = CType(Attributes(0), DataClassAttribute)
  End If
  Return dca
End Function

Listing 8

Public Function GetConfigurableObjects( _
       ByVal AssemblyFileName As String) _
       As ArrayList
  Dim asm As [Assembly]
  Dim ReturnValue As New ArrayList

  ' Load the assembly from disk
  asm = [Assembly].LoadFrom(AssemblyFileName)

  ' Process each type in the assembly
  For Each t As System.Type In asm.GetTypes
    ' Obtain a list of all attributes attached
    ' to this type, but filter the list so
    ' that it includes only our 
    ' DataClassAttribute.
    Dim Attributes() As Object = _
        t.GetCustomAttributes( _
                 GetType(DataClassAttribute), _
                 False)

    If Attributes.Length > 0 Then
      ' The attribute exists.  Return the 
      ' DataClassAttribute
      ReturnValue.Add( _
          CType(Attributes(0), _
                DataClassAttribute))
    End If
  Next

  Return ReturnValue
End Function