Monday, January 08, 2007

Reflection in .NET

A couple of days ago I used Reflection for the first time in a .NET project. Very cool.

I have always known the System.Reflection namespace was there and a very high level understanding of what it does, but never actually used it or seemed to have a need to.

Well, on Wednesday I had a need for it. I was trying to map bits of XML structure into strongly-typed .NET classes. So I'd have something like this:


weirdo-stuff
3
XR34R
278.42

...that I wanted to turn into a .NET class.

So my dilemma was this: I had to write virtually the same piece of code over and over for each node in the XML to map it to the appropriate property in the class I was building and cast the value from the XML to the appropriate type.

So I thought, "...what I need is a function where I can pass in the property name, the XML node name and data type and have it populate the correct property with the correct type". And then I said it out loud to Ryan. And he said, "..in Java you'd use Reflection." "Ahhh..." I said.

With Reflection you can query an object for meta data at run-time.

In .NET everything that inherits from System.Object, gets a method called getType(). This returns a "System.Type" type. Then on that type object, you can ask for information about a property of the object by passing a string of the property name. Then you can tell the reflected property information to set a value for that property by passing an object for the value and a reference to object instance that contains the property.

Here is a snippet of the code:

Type theType = obj.GetType();
PropertyInfo propInfo = theType.GetProperty(propertyName);
//To hold the value of the property we wish to set
object propValue = new Object();
//The type of the property we wish to set
Type propType = propInfo.PropertyType;
//The string value from the XML, which we will convert to the appropraite type
//for the property we wish to set
string xmlValue = xmlMarkupRoot[childNodeName].InnerText;
//Here we'll need to test for the basic types
if(propType == (Type.GetType("System.Double")))
{
propValue = Convert.ToDouble(xmlValue);
}
else if (propType == (Type.GetType("System.String")))
{
propValue = xmlValue;
}
else if (propType == (Type.GetType("System.Int16")))
{
propValue = Convert.ToInt16(xmlValue);
}
else if (propType == (Type.GetType("System.Int32")))
{
propValue = Convert.ToInt32(xmlValue);
}
else if (propType == (Type.GetType("System.Single")))
{
propValue = Convert.ToSingle(xmlValue);
}
else if (propType == (Type.GetType("System.Boolean")))
{
propValue = Convert.ToBoolean(xmlValue);
}
propInfo.SetValue(obj, propValue, null);
Pretty sweet.

No comments: