Friday, January 12, 2007

Reflection: Modify value types by reflection

Yestarday I have seen a post in Experts-Exchange related with using reflection on structure in .net. The guy is trying to modify the content of the structure via reflection by passing an instance of the structure to a method. On first sight this is something real normal - using reflection go through fields, properties, etc., change values, invoke members and at the end of the method you will have complete new data in your structure.

Yes, but no thanks. This could not happend because the structure is value type and not reference type. In this case the code

MyStruct _name = new MyStruct();
_name.familyName = "Smith";
_name.givenName = "John";
foreach (FieldInfo fi in _name.GetType().GetFields())
{
fi.SetValue(_name, "set value test");
}

will not change the content of the structure at all. But this work perfect if you would use class instead of structure. I've decided to check if anybody on the net is trying to do things lilke this and of cource I saw a lot of articles on the net where programmers are talking about using ValueType object to work with strucutre in this situation.

So trying to move forward I have written this:

MyStruct _name = new MyStruct();
_name.familyName = "Smith";
_name.givenName = "John";

ValueType vt = _name;
FieldInfo[] fis = _name.GetType().GetFields();
for (int i = 0; i <>
{
FieldInfo fi = fis[i];
if (_name.GetType().IsValueType)
{
fi.SetValue(vt, "set value test");
fi.SetValue(_name, "Test");
}
}

This code should work like a sharp. In the above code when is using

fi.SetValue(_name, "Test");

the content of the structure will not be changed. But - the vt variable which is ValueType will be changed via the line

fi.SetValue(vt, "set value test");

So I believe this was the right way and the task is finished. I wanted to help the guy to change the values of the structure, I have found that using ValueType class is the right direction to do this and at the end of the code above I have the changed structure's fields.

Opps! I do not have the structure's fields changed! I do have changed the fields of the ValueType variable changed. So because the ValueType class is the base class of all value types, it is normal that you can not cast the variable vt back to the structure MyStructure type.

So at the end of writting this code I had changed the values of the fields but the result that had to return was not of type MyStruct and of type ValueType. What a hell? It is obviously that you could not change the structure's fields by reflection - BECAUSE IT IS A VALUE TYPE!

Ok! But there should be a way! There must be a way of passing to a method strucutre instance and return as a result instance of the same strucutre with changed by Reflection values.

All I had moving around is in some way calling the constructor of the structure by passing parammeters. Using Reflection is it not possible. Why? BECAUSE IT IS A VALUE TYPE!. And the code of using ConstructorInfo.Invoke will produce the same result like the code above - No change to the structure instance. Is there any other way a constructor can be called?

Yes! There is a way! In System namespace there is a class called Activator. And was happy to read the brief description of this class:
"Contains methods to create types of objects locally or remotely, or obtain references to existing remote objects. This class cannot be inherited."

So researching the class' methods I have found that there is a method CreateInstance that return the newly created instance (see that when using reflection and call the ConstructorInfo.Invoke you do not return any instance.The reflection is used the passed object and is trying to create the new instance on the passed variable).

So after reading a while and trying it I have finally written this which works like a charm:


public static MyStruct ChangeValues(MyStruct previousVersion)
{
MyStruct changedVersion = default(MyStruct);
ValueType valueType = previousVersion;

MemberInfo[] members = valueType.GetType().GetMembers();

for (int memberIndex = 0; memberIndex < style="color:#3333ff;">if (members[memberIndex].MemberType == MemberTypes.Field)
{
if (valueType.GetType().GetField(members[memberIndex].Name).FieldType == typeof(String))
{
changedVersion = (MyStruct)Activator.CreateInstance(changedVersion.GetType(), new object[] { "test", 3 });
}
}
}
return changedVersion;
}


public struct MyStruct
{
public String variableString;
public Int32 variableInt32;
public Boolean variableBoolean;

public MyStruct(String var1, Int32 var2)
{
variableString = var1;
variableInt32 = var2;
variableBoolean = false;
}
}

This finally, I think, finish the task of passing parameter of structure to the method and return a changed instance of the same structure using Reflection.

Regards

Tuesday, January 9, 2007

Debugging problems in .NET

I have faced very often these days problems when I started my Studio in Debuging mode.
Also many time in ExpertsExchange I'm talking with members in exaclty the same problems.

One of the very good document I have founded on the net is "my best friend" in all these situations. And when yestarday I found that is really hard to find this document out i decided to add another link to this document.

It is really cool to read it. Here it is