Wednesday, September 16, 2009

Using Reflection to Map Properties on Objects by their String Name

You might have an object that has the following properties:

In addition, you can not refractor the code to use a list of objects or other method and are stuck with having several properties with a similar purpose on a single object. You may have coded logic in a ‘Case’ statement to determine which property to set on the object based on some other logic like the sample UI event and associated method below:

Public Sub MyUIEvent()

UpdateProperty(Me.txtValue1.ClientID, MyObject)
UpdateProperty(Me.txtValue2.ClientID, MyObject)
UpdateProperty(Me.txtValue3.ClientID, MyObject)
UpdateProperty(Me.txtValue4.ClientID, MyObject)
UpdateProperty(Me.txtValue5.ClientID, MyObject)

End Sub

Private Sub UpdateProperty(ByVal TextBoxID As String, ByVal MyObject As MyCustomObject)

Select Case TextBoxID

Case "txtValue1"
MyObject.Value1 = txtValue1.Text
Case "txtValue2"
MyObject.Value2 = txtValue2.Text
Case "txtValue3"
MyObject.Value3 = txtValue3.Text
Case "txtValue4"
MyObject.Value4 = txtValue4.Text
Case "txtValue5"
MyObject.Value5 = txtValue5.Text
End Select

End Sub

In this case you can change your ‘UpdateProperty’ method to use Reflection to map the property name on an object using its String name equivalent. You can infer the UI element to property name logic mapping inline in the call to your new method. This saves a lot of code, especially if you have more that 5 properties that are involved in the ‘Case’ statement.

Take a look to the modified method named ‘UpdatePropertyUsingReflection’ and the change to the parameter values passed in to reduce the code using Reflection:

Public Sub MyUIEventCallingReflectionMethod()

'Call the method to Update the object's property based on the name value of the property provided:
UpdatePropertyUsingReflection(Me.txtValue1.Text, MyObject, MyObject.Value1.ToString())
UpdatePropertyUsingReflection(Me.txtValue2.Text, MyObject, MyObject.Value2.ToString())
UpdatePropertyUsingReflection(Me.txtValue3.Text, MyObject, MyObject.Value3.ToString())
UpdatePropertyUsingReflection(Me.txtValue4.Text, MyObject, MyObject.Value4.ToString())
UpdatePropertyUsingReflection(Me.txtValue5.Text, MyObject, MyObject.Value5.ToString())

End Sub

Private Sub UpdatePropertyUsingReflection(ByVal TextBoxValue As String, ByVal MyObject As MyCustomObject, ByVal PropertyToUpdate As String)

'Use Reflection to get the property attributes for the Property Name Value passed into Sub():
Dim myProperty As System.Reflection.PropertyInfo = MyObject.GetType().GetProperty(PropertyToUpdate)
'Set the value on the object passed in using the setvalue method on the reflected property.
myProperty.SetValue(MyObject, TextBoxValue, Nothing)

End Sub

So there you have it; the (2) lines of code using Reflection replaced the larger ‘Case’ statement needed to determine which property to update.

Of course, the example used here was not the only use for this method and could be applied in many situations. The main goal was to show how to reflect properties using their String type name equivalent. There is some overhead associated with Reflection in .NET, but we can leave that for another day. Depending on its usage, this method can save a lot of code and be used not only with object properties, but in calling methods on objects by their String name as well.