Reflectively Yours
I’ve been doing a lot of work with serialization in .Net, which also means I’ve been doing a lot with .Net’s reflection API. I’m sure you may be wondering why we didn’t just use IXmlSerializable or something like that. The long and the short of it is that there were reasons. Mainly it was the fact that we wanted to use the same set of attributes to pull double duty for serialization and for the user interface. I won’t bore you with the details of the serialization approach, the focus of today is something that utterly surprised me.
If you see the code below, do you think it will work?
public class PersonalClass
{
private string ccInfo = "XXXXXXXXXXXX1234";
}
public class DeviousReflection
{
public void main(string[] args)
{
FieldInfo field = typeof(PersonalClass).GetField("ccInfo",
/* binding flags for instance and non-public */);
PersonalClass instance = new PersonalClass();
string gotcha = field.GetValue(instance);
field.SetValue(instance, new Object[] {"Really Devious"});
}
}
I apologize in advance if I mistyped something from the API, it was from memory. So for the reflection uninitiated, what I’ve done is set up an object with a private member that I shouldn’t be able to touch. Next I set up a separate class that should never have access to the private members of another class to perform some reflection. I looked at the type of the class I wanted to exploit (... um, access …) and got a reference to the private field as described through reflection. I then took an instance of the class I wanted to exploit, and used the reflection to not only get its current value but to set a new value.
Now, if this were the Java VM you would be out of luck. The JVM has been extra vigilant about ensuring proper access to class members both by the compiler and reflectively through the VM. The protections are built in at the lowest level.
We’re talking .Net here, so as long as you can get an instance of the FieldInfo for the private field, you can get and set information in private fields. I even tested this out in classes that weren’t in the same assembly. It still works. I’ll leave the implications this has for you to your imagination. However, this is a really good reason to not use “Magic Values” hard coded in your application. I don’t even have to know the structure of your application. I can iterate through the fields and find something that looks promising.
What this means for my application and the serialization problem is that it really frees the developers up to develop the way they normally would. No need to artificially make something public just because you want to write it to a file. What this means for folks releasing .Net applications for money to the world at large is that code obfuscation tools become really important. An application built for hire is probably OK. There is no real security through obscurity, but at least it makes it a bit harder to find where the important stuff is since everything looks the same.
.Net Asynchronous Features Require Some Rethinking
Disclaimer: I’m originally a Java guy, and I know all kinds of asynchronous patterns and approaches that work in the Java world. The .Net approach to multi-threading and asynchronous applications is quite a bit different. In some ways the way that Microsoft approached the problem is more problematic. I stumbled across someone’s code for a small C# ray tracer with a fixed scene. I figured that this would be the perfect place to start playing with asynchronous code. Microsoft likes to hide things from you. I find this a bit problematic while trying to find out what is going wrong. Case and point: my assumptions about the way lambdas and closures ought to work (from my Ruby background) turned out to be wrong. Consider this code snippet:
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
RenderColorDelegate px = RenderColor;
px.BeginInvoke(x, y, scene, ar =>
{
Color c = px.EndInvoke(ar);
RenderPixelDelegate dl = RenderPixel;
pictureBox.Invoke(dl,new Object[]{x,y,c});
}, null);
}
}
Before I go into the surprise, let me tel you what this code is doing. This code is launching the rays from the view port one pixel at a time to calculate the color for that pixel. The px.BeginInvoke call is done on a delegate I had to create to alias the method I wanted to make asynchronous. I needed to pass in the variable “x”, “y”, and the scene that was passed in to the Render method. The original code makes use of synchronous calls, and behaves exactly as you would expect. X is always between 0 and one less than screenWidth. Y is always between 0 and one less than screenHeight. Now here is the surprise: when calling the methods asynchronously X can become greater than screenWidth!
Let me state that again in other terms: the values you pass in to the asynchronous method are not the values that end up being used. It behaves as a reference to the integer you pass in, and any call to x++ will increment the value on any asynchronous calls that have not been executed yet. That should alarm you. This can be (and was in this case) the source of serious and difficult to trace errors. With Ruby and Java anonymous classes, the values for x and y are frozen at the moment the asynchronous block is created. However, with .Net it is not. In order to fix the problem we have to copy x and y to new integers strictly for the purpose of passing in to the asynchrnous call:
for (int y = 0; y < screenHeight; y++)
{
for (int x = 0; x < screenWidth; x++)
{
// Necessary to work around bug
int cx = x;
int cy = y;
RenderColorDelegate px = RenderColor;
px.BeginInvoke(cx, cy, scene, ar =>
{
Color c = px.EndInvoke(ar);
RenderPixelDelegate dl = RenderPixel;
pictureBox.Invoke(dl,new Object[]{cx,cy,c});
}, null);
}
}
The “pictureBox.Invoke” method should be familiar to .Net and Java UI developers. Essentially screen drawing and refreshing has to be done within the GUI thread. The “Invoke” method makes that happen when you are in another thread. The style of asynchronous call that I used included the callback function. This makes the redraw happen after the calculation is done.
When it comes to more traditional Thread manipulation, Java’s bag of tricks is a bit more complete. That may have changed with .Net 4.0 but I need to stick with 3.5. For example, the Future construct is really what I need. A Future is basically the promise of a value for when you need it later. It allows you to start processing a complex algorithm before you need the result, and pause for the result only when you really need it. It works for lazy initialization, but it’s more effective when you have a number of complex calculations you need to merge together. Java also has some good thread pool support, tasks, and other features. The Fork/Join approach in Java7 is also a very effective way to divvy up work. .Net 4.0 may have something similar to that, but both of those are taboo for new work for the time being.
All in all, I only scratched the surface. The delegate BeginInvoke() approach was designed for asynchronous event processing. It wasn’t really designed for more serious multi-threading. In fact, the way I used it for the ray tracer was the wrong tool for the job.
The bottom line is that I have to change the way I think about multi-threaded application design in the .Net platform. Some of the principles I’ve picked up from other languages still convey—but there’s a new twist on them. It’s to be expected. However, do be cautious of the delegate problem I ran into. It’s not good to have your values change underneath of you.
