views:

2140

answers:

2

I've got a set of static "enumeration" classes that I'm using to hold meaningful variable names to represent meaningless code values I receive on an input file. Here's an example of one.

Public Class ReasonCodeValue
    Private Sub New()
    End Sub
    Public Shared ReadOnly ServiceNotCovered As String = "SNCV"
    Public Shared ReadOnly MemberNotEligible As String = "MNEL"
End Class

I want to write a method that will accept the type of one of these static classes and a string value and determine whether the value is one of the static field values. I know how to get the instance fields for a specific object, and I know how to get a list of static fields for a specific type; what I can't figure out is how to get the static field values without an instance. Here's what I've got so far.

Public Function IsValidValue(ByVal type As Type, ByVal value As String) As Boolean
    Dim fields = type.GetFields(BindingFlags.Public Or BindingFlags.Static)
    For Each field As FieldInfo In fields
        DoSomething()
    Next
End Function

I supposed I could make the enumeration classes non-static just so I can create an instance to pass to FieldInfo.GetValue inside my validation method. I'd rather keep my class the way it is if I can.

I see a method called GetRawConstantValue. It looks dangerous. Will that give me what I'm looking for? Any other ideas?

+8  A: 

Call

field.GetValue(Nothing)

and it'll be fine. You don't need an instance for static members.

I don't think GetRawConstantValue is what you want - I'd stick to the code above.

Jon Skeet
Hey, you put it in VB for me. Never thought of passing a null. Thanks.
John M Gant
Ask a question in VB and I'll try to answer it in VB. Sometimes it goes badly wrong, but in this case it wasn't too hard :)
Jon Skeet
Another JS fact: Jon Skeet computes his answers in an universal IL and then translates it to the appropriate source code...
Jorge Córdoba
+2  A: 

Looking at what you're trying to do in the larger sense, perhaps this would be a better fit:

Public Interface ICustomEnum(Of T)
    Function FromT(ByVal value As T) As ICustomEnum(Of T)
    ReadOnly Property Value() As T

    ''// Implement using a private constructor that accepts and sets the Value property, 
    ''// one shared readonly property for each desired value in the enum,
    ''// and widening conversions to and from T.
    ''// Then see this link to get intellisense support
    ''// that exactly matches a normal enum:
    ''// http://stackoverflow.com/questions/102084/hidden-features-of-vb-net/102217#102217
End Interface

'
''' <completionlist cref="ReasonCodeValue"/>
Public NotInheritable Class ReasonCodeValue
    Implements ICustomEnum(Of String)

    Private _value As String
    Public ReadOnly Property Value() As String Implements ICustomEnum(Of String).Value
        Get
            Return _value
        End Get
    End Property

    Private Sub New(ByVal value As String)
        _value = value
    End Sub

    Private Shared _ServiceNotCovered As New ReasonCodeValue("SNCV")
    Public Shared ReadOnly Property ServiceNotCovered() As ReasonCodeValue
        Get
            Return _ServiceNotCovered
        End Get
    End Property

    Private Shared _MemberNotEligible As New ReasonCodeValue("MNEL")
    Public Shared ReadOnly Property MemberNotEligible() As ReasonCodeValue
        Get
            Return _MemberNotEligible
        End Get
    End Property

    Public Shared Function FromString(ByVal value As String) As ICustomEnum(Of String)
        ''// use reflection or a dictionary here if you have a lot of values
        Select Case value
            Case "SNCV"
                Return _ServiceNotCovered
            Case "MNEL"
                Return _MemberNotEligible
            Case Else
                Return Nothing ''//or throw an exception
        End Select
    End Function

    Public Function FromT(ByVal value As String) As ICustomEnum(Of String) Implements ICustomEnum(Of String).FromT
        Return FromString(value)
    End Function

    Public Shared Widening Operator CType(ByVal item As ReasonCodeValue) As String
        Return item.Value
    End Operator

    Public Shared Widening Operator CType(ByVal value As String) As ReasonCodeValue
        Return FromString(value)
    End Operator
End Class

And then using this link you might be able to get intellisense support that exactly matches that of a normal enum:
http://stackoverflow.com/questions/102084/hidden-features-of-vb-net/102217#102217

Joel Coehoorn
Joel, this is the exact answer I'm looking for on question 935544 (and a very good answer for the current question too). If you could answer that question with a link to this answer, that would be helpful. Thanks for the extra information. The hidden features link is excellent.
John M Gant
all done.
Joel Coehoorn