There are three classes which will help you; TypeDescriptor, PropertyDescriptor and PropertyDescriptorCollection. They are all located in the System.ComponentModel namespace.
Imports System.ComponentModel
We'll be using the following class for this example:
Public Class Foo
'Implements ICustomTypeDescriptor (Optional)
Public Property A() As String
Public Property B() As Date
Public Property C() As Integer
Public Property D() As Boolean
Public Overrides Function ToString() As String
Return String.Format("A='{0}', B='{1}', C='{2}', D='{3}'", Me.A, Me.B, Me.C, Me.D)
End Function
End Class
Get all the properties by invoking the static method GetProperties
of the TypeDescriptor
class. It returns a collection of PropertyDescriptor
classes - your properties. Then you simply invoke either the SetValue
and/or GetValue
methods. Note that you can implement a custom type descriptor by implementing the ICustomTypeDescriptor interface.
Private Sub RunTest()
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(Foo))
Dim ignoreCase As Boolean = True
Dim foo1 As New Foo()
properties.Find("A", ignoreCase).SetValue(foo1, "hello")
properties.Find("B", ignoreCase).SetValue(foo1, Date.Now)
properties.Find("C", ignoreCase).SetValue(foo1, 1234I)
properties.Find("D", ignoreCase).SetValue(foo1, True)
'Get property value:
'Dim a As String = CType(properties.Find("A", ignoreCase).GetValue(foo1), String)
Debug.WriteLine(foo1.ToString())
End Sub
Output: (immediate window)
A='hello', B='30.11.2014 11:14:39', C='1234', D='True'
Extension
To expand this even further one can create some extension methods.
Imports System.Runtime.CompilerServices
Public Module Extensions
<Extension()>
Public Function GetProperty(Of TComponent)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As Object
Return TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component)
End Function
<Extension()>
Public Function GetProperty(Of TComponent, TValue)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As TValue
Return CType(TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component), TValue)
End Function
<Extension()>
Public Sub SetProperty(Of TComponent)(instance As TComponent, propertyName As String, value As Object, Optional ByVal ignoreCase As Boolean = True)
TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).SetValue(instance, value)
End Sub
End Module
Now it's very easy to set/get a property value by name.
Private Sub RunTest()
Dim foo1 As New Foo()
foo1.SetProperty("A", "hello")
foo1.SetProperty("B", Date.Now)
foo1.SetProperty("C", 1234I)
foo1.SetProperty("D", True)
'Get property value:
'Dim a As String = CType(foo1.GetProperty("A"), String)
'Dim a As String = foo1.GetProperty(Of String)("B")
Debug.WriteLine(foo1.ToString())
End Sub
Output:
A='hello', B='30.11.2014 11:18:17', C='1234', D='True'