Some time ago I wrote some code so set object properties/fields at runtime by reading an XML config file. The code was quite straightforward using reflection and all seemed well until someone decided to add a structure and tried to set the structures fields. This failed because a structure is a reference type an therefore its contents are copied when passed as a ByVal parameter. However after changing the parameters to ByRef the code still didn’t work as the final call to FieldInfo.SetValue() was out of my reach as it is part of the .Net framework. Some research on the web showed I wasn’t the first to run into this problem but no one seemed to have a solution as far as I could determine. Some further investigation did result in a fix though. If you cast passed to structure to a variable of type ValueType and used that instead of a generic type Object
Old code (doesn’t work for the structure):
Module
Module1
Sub
Main()
Dim
tc As
New
TestClass
Dim
ts As
TestStructure
' Using
an object
tc.Name =
"Maurice in an object"
Console.WriteLine(tc.Name)
ChangeName(tc)
Console.WriteLine(tc.Name)
' Using a
structure
ts.Name =
"Maurice in a structure"
Console.WriteLine(ts.Name)
ChangeName(ts)
Console.WriteLine(ts.Name)
Console.ReadLine()
End
Sub
Sub
ChangeName(ByRef
var As
Object)
Dim
t As
Type
Dim
fi As
Reflection.FieldInfo
t = var.GetType()
fi = t.GetField("Name")
fi.SetValue(var,
"Maurice de Beijer")
End
Sub
End
Module
Structure
TestStructure
Public
Name As
String
End
Structure
Class
TestClass
Public
Name As
String
End
Class
New code:
Sub
ChangeName(ByRef
var As
Object)
Dim
vt As
ValueType
Dim
t As
Type
Dim
fi As
Reflection.FieldInfo
t = var.GetType()
fi = t.GetField("Name")
If
t.IsValueType Then
vt = var
fi.SetValue(vt,
"Maurice de Beijer")
Else
fi.SetValue(var,
"Maurice de Beijer")
End
If
End
Sub
Interestingly creating an overloaded ChangeName function with a parameter typed as ValueType doesn’t work, the function with Object will still be called with the structure.
|