Setting structure members using System.Reflection

G

Guest

I have two questions;

1) When executing the sub routine "TestStructure", I'm trying to update the
member "intTyres" in the structure "structureCar" dynamically using
System.Reflection. The code executes, but the value does not change, nor is
there an exception thrown.

2) Read comments in sub routine "TestIntegerProperty"


Imports System.Reflection
Imports System.Windows.Forms

Public Class cReflection

Public Structure structureCar
Public intTyres As Integer
Public strName As String
End Structure

Dim mTestStructure As New structureCar

Dim mTestIntegerProperty As New System.Windows.Forms.Button

Public Sub TestStructure()

Dim myType As Type = GetType(structureCar)
Dim myFieldInfo As FieldInfo = myType.GetField("intTyres",
BindingFlags.NonPublic Or BindingFlags.Public Or BindingFlags.InvokeMethod Or
BindingFlags.Instance Or BindingFlags.SetField)
'The next line of code is supposed to change the value of the
"intTyres" member to 5, but it stays zero.
'When a class is used instead of a structure it works. (this is not
an option)
myFieldInfo.SetValue(mTestStructure, 5) 'This does not generate an
exeception

End Sub


Public Sub TestIntegerProperty()
Dim objValue As Object

objValue = "200"

Dim myType As Type = GetType(System.Windows.Forms.Button)
Dim myFieldInfo As PropertyInfo = myType.GetProperty("Left")
'The following line of code does not change the value of the "Left"
property, becuase objValue is seen as string.
'Assigning an integer to objValue does however work, but this is not
an option for us for various reasons. How do I get the method "SetValue" to
accept the object, "objValue", as a string, but convert it to an integer(if a
number is a string, declared as an object, does the object not automatically
get converted to an integer, because the property expects an integer?).
myFieldInfo.SetValue(mTestIntegerProperty, objValue, Nothing)
'Exception gets generated.

'The following doesn't work as well
'I am trying to ctype the "string" objValue to the PropertyType of
the "Left" property
'Uncomment line 41 and 42 to see error

'----------------------------------------------------------------------------------------------------------------------
'Dim tType As Type = Type.GetType(myFieldInfo.PropertyType.FullName)
'How do I create a dynamic type so that "Ctype" can see the type
"tType"
'myFieldInfo.SetValue(mTestIntegerProperty, CType(objValue, tType),
Nothing)

'----------------------------------------------------------------------------------------------------------------------
End Sub

End Class
 
J

Jon Skeet [C# MVP]

Andre said:
I have two questions;

1) When executing the sub routine "TestStructure", I'm trying to update the
member "intTyres" in the structure "structureCar" dynamically using
System.Reflection. The code executes, but the value does not change, nor is
there an exception thrown.

Of course the value doesn't change - you're passing a value type, which
is then being boxed, and you're not keeping a reference to the boxed
version.

Try declaring a variable of type Object, setting its value to the boxed
version of mTestStructure, then calling SetValue, then unboxing back to
mTestStructure.
 
G

Guest

Hi Jon

Thanks for your reply. I'm not familiar with the terms boxed and unboxed.
Could you please give me a quick example, using my example.

Regards
Andre
 
J

Jon Skeet [C# MVP]

Andre said:
Thanks for your reply. I'm not familiar with the terms boxed and unboxed.
Could you please give me a quick example, using my example.

Boxing is what happens when you use a value type as a reference type,
and unboxing is the taking the value out of the box object.

I can't easily come up with the proper example in VB.NET, as I'm mainly
a C# coder, but in C# it would be:

object o = mTestStructure;
myFieldInfo.SetValue(o, 5);
mTestStructure = (structureCar) o;

Here's a complete example in C#:

using System;
using System.Reflection;

struct Foo
{
public int x;
}

class Test
{
static void Main()
{
Foo f = new Foo();
f.x = 10;

FieldInfo fi = typeof(Foo).GetField("x");

object o = f;
fi.SetValue (o, 3);
f = (Foo)o;

Console.WriteLine (f.x);
}
}
 
G

Guest

Hi Jon

Thank-you for the example.

I've converted every line of code to Visual Basic .net and I have the exact
same problem as before. When I ran the C# code, the example worked, but when
I ran the VB code, the cursor steps over the code, but does not change the
value of x in the structure. Is this a Visual basic bug? Please copy this
code and paste it in a Visual Basic Console project and you will see what I
mean. Please help!

Regards
Andre

Imports System
Imports System.Reflection

Public Structure Foo
Public x As Integer
End Structure

Public Class Test

Public Shared Sub Main()
Dim f As New Foo
f.x = 10

Dim fi As FieldInfo = GetType(Foo).GetField("x")

Dim o As Object = f
fi.SetValue(o, 3)
f = CType(o, Foo)

Console.WriteLine(f.x)
End Sub
End Class
 
J

Jon Skeet [C# MVP]

Andre said:
Thank-you for the example.

I've converted every line of code to Visual Basic .net and I have the exact
same problem as before. When I ran the C# code, the example worked, but when
I ran the VB code, the cursor steps over the code, but does not change the
value of x in the structure. Is this a Visual basic bug? Please copy this
code and paste it in a Visual Basic Console project and you will see what I
mean. Please help!

This is very odd. The VB compiler seems to be calling
RuntimeHelpers.GetObjectValue for no reason that I can make out.

I would ask on the VB.NET group if I were you, with the sample program
you've just posted. It looks like it's a VB.NET quirk to me :(
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top