Introduction
When I'm developing an application, I often like to use enumerators as properties of my objects to improve the readability of my code. Often, the enumerator value will come from a table in the database. For example, we might have an enumerator resembling something like this:
Public Enum EmailStatus
Unread
Read
Deleted
End Enum
Using enumerators is very useful when developing classes since it provides a strongly-typed way to implement business logic:
If Me.EmailStatus = EmailStatus.Read Then
End If
Nevertheless, we're bound to run into a problem when we need to display the enumerator's value to the user. The same is true when we try to save the object's state to the database. Luckily, we can use a custom attribute to give us this type of functionality.
Background
This article will show you a basic implementation of how to use custom attributes in your enumerators. You can certainly expand the custom attribute to store more information about the field in the enumerator you wish to enhance.
Using the code
Creating a custom attribute is very much like creating any other class. The main difference is that we must inherit from System.Attribute
.
Public Class SmartEnumeratorAttribute
Inherits System.Attribute
End Class
Once we've done this, we must set the AttributeUsage
of the class. Since we're only going to apply this to fields of an enumerator, the parameter should be set to AttributeTargets.Field
. This tells the compiler that when using this attribute, it can only be applied to a field. We also don't want to allow the developer to apply this attribute to the same field multiple times, so we must set AllowMultiple = False
.
<AttributeUsage(AttributeTargets.Field, AllowMultiple:=False)> _
Public Class SmartEnumeratorAttribute
Inherits System.Attribute
End Class
At this point, we can begin to define the extended properties that we want a particular field of the enumerator to return. Since we want to be able to display the value to the user interface, we will create a Description
property. We also want to save the enumerator's value to the database using a foreign key of type Integer
. We will also be creating a public constructor that accepts the value of our properties to make the initialization of the attribute easier:
Private mDatabaseValue As String
Private mDescription As String
Public Property DatabaseValue() As String
Get
Return mDatabaseValue
End Get
Set(ByVal Value As String)
mDatabaseValue = Value
End Set
End Property
Public Property Description() As String
Get
Return mDescription
End Get
Set(ByVal Value As String)
mDescription = Value
End Set
End Property
Public Sub New(ByVal DatabaseValue As String, _
ByVal Description As String)
mDatabaseValue = DatabaseValue
mDescription = Description
End Sub
Finally, to create the actual enumerator, just add the custom attribute to each field in the enumerator:
Public Enum EmailStatus
<SmartEnumerator("1", "New E-mail")> Unread
<SmartEnumerator("2", "Read E-mail")> Read
<SmartEnumerator("3", "Deleted E-mail")> Deleted
End Enum
Accessing the custom attributes will involve the use of the System.Reflection
namespace since the attribute is being applied to the individual fields of the enumerator:
Imports System
Imports System.Reflection
Imports System.ComponentModel
Public Class SmartEnum
Public Shared Function GetDescription(ByVal _
obj As Object) As String
Dim t As Type = obj.GetType
Dim fInfo As FieldInfo = _
t.GetField(System.Enum.GetName(t, obj))
Dim attr As SmartEnumeratorAttribute = _
DirectCast(fInfo.GetCustomAttributes(_
GetType(SmartEnumeratorAttribute), _
False)(0), SmartEnumeratorAttribute)
Return attr.Description
End Function
End Class
Points of Interest
Hopefully, this article has given you a better idea of how to use custom attributes with enumerators to increase the readability of your code when your enumerators need to interact with a database or display their value to the user.