1

I have a large structure (50+ members) like this:

Public Structure DagDay    
    Public DayDate As Date
    Public DayEcoZone As String
    Public DayOrd As Boolean
    Public DayHelg As Boolean
    Public DayAfton As Boolean
    Public DayEvent As Boolean
    Public DayEventText As String
    Public DayIncVat As Boolean
    Public DayOmsTot As Integer
    Public DayOmsCat1 As Integer
    Public DayOmsCat2 As Integer
    Public DayOmsCat3 As Integer
    .....
End Structure
...
Dim ThisDay as DagDay

Now i'm trying to let a function set any specific members value in in the variable ThisDay, but I can't figure out how (else then a large select.. Case..).

Public Function SetValue(ByVal Field As String, ByVal value As VariantType) As Boolean

Select Case Field

            Case "DayDate"
                ThisDay.DayDate = value
            Case "DayEcoZone"
                ThisDay.DayEcoZone = value
            Case "DayOrd"
                ThisDay.DayOrd = value
            Case "DayHelg"
                ThisDay.DayHelg = value
         .....

        End Select

I would like to be able to do something like this (pseudo code):

Public Function SetValue(ByVal Field As String, ByVal value As VariantType) As Boolean

        ThisDay.[Field] = value
        Return True
End Function 

How can I use a string variable to reference a specific member (field) in a structure?

4
  • What is VariantType ? Commented May 17, 2017 at 23:21
  • 1
    @Plutonix, I think it is a misuse of the Microsoft.VisualBasic.VariantType enum. Commented May 18, 2017 at 0:03
  • Where are you getting the value for Field that you pass in? Commented May 18, 2017 at 0:35
  • @ Enigmativity, the value for Field comes from the name-property of corresponding input field (TextBox or CheckBox):es-controls that are dynamically created in one of three different Forms. Commented May 18, 2017 at 1:04

1 Answer 1

2

Use Reflection:

I don't know the VB.NET syntax, but in C# it would be this:

static void SetValue(Object parent, Object newFieldValue, String fieldName) {

    FieldInfo field = parent.GetType().GetField( fieldName, BindingFlags.Public | BindingFlags.Instance );
    field.SetValue( parent, newFieldValue );
}

Because fieldName is arbitrary input, you can prevent incorrect fieldName values by using nameof() to ensure you always specify a valid field-name.

Note we want x.GetType() instead of typeof(x) because we want the runtime type, not the compile-time type (which is always Object).

Even though you're working with a value-type struct, pass-by-value semantics don't apply because it's boxed as an Object (so it's actually passed-by-reference) so setting a field will work as though it were a class (reference-type).

Usage:

MyStruct value;
value.FieldFoo = "hello";
SetValue( value, "world", nameof(value.FieldBar) );
Assert.AreEqual( "world", value.FieldBar );

My VB.NET is a bit rusty, but I think this would be it:

Public Shared Sub SetValue(parentAs Object, newFieldValue As Object, fieldName As String)

    Dim field As FieldInfo = parent.GetType().GetField( fieldName, BindingFlags.Public Or BindingFlags.Instance )
    field.SetValue( parent, newFieldValue )

End Sub

VB.NET now has the NameOf operator which works the same way as C#'s.

Usage:

Dim value As New MyStruct
value.FieldFoo = "hello"
SetValue( value, "world", NameOf(value.FieldBar) )
Assert.AreEqual( "world", value.FieldBar )
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a million for quick and excellent answer, testing this now.
Works like a charm! Excellent explanation! Just needs a "Imports System.Reflection" as well.. THANKS!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.