
Dynamic languages are getting more popular these days and I'm one of those guys that likes to try new things so I jumped on the dynamic language wagon. One of the things I'm looking for is where it is actually faster than C# (Not only in the language constructs, but with engine startup as well). The fact that I'm looking where it is faster is because I want a good solution to reflect some of my Reflection constructs with a more dynamic approach using python or some other dynamic language.
Last week I've been working on an object persistence framework that I'm going to use in my open source scheduling application. I've created the framework because CSLA.NET frameworks were a bit of a hassle to work with and NHibernate was a bit too much for me, mostly because I wanted to partially load types and don't need support for persisting relations, I will be doing this myself. The framework I created uses the enterprise library for the data access components. This offers me with a database independent method of working with data. However it doesn't make my work any less hard when it comes to writing the plumbing for loading and saving entities. This still requires a few hundred lines of code.
To solve the plumbing problem I wrote some code that finds all properties of an type that are marked with the PersistentProperty attribute. These are cached once and used during lifespan of the appdomain. This cuts back on the reflection time. However the framework still used reflection to set values of properties on objects. My computer is fast enough to handle this, but it buggers me ;P
This is where I got my first good appliance of IronPython. Instead of using reflection to assign loaded values to properties of an object, I used a python script to do this. The script is as simple as this:
# The following objects are available in this script
#
# ObjectUnderConstruction - The object to construct
# DataReader - The datareader containing the values to insert
# PropertyFieldDictionary - The properties of the object
# Construct the fields for the object
for propertyName in PropertyFieldDictionary.Keys:
fieldValue = DataReader.GetValue(DataReader.GetOrdinal(PropertyFieldDictionary[propertyName]))
setattr(ObjectUnderConstruction,propertyName,fieldValue)
One of the weirdest features of IronPython and Python in general is the fact that typing is dynamic. Every method and class is in fact a variable itself[1]. My theory is that this should eliminate the costs of reflection and should make my code a lot faster. There is however one catch, the engine can be actually slower to start than it would be to just use reflection. I haven't tested this yet, so I might be all wrong on this. The application will host the IronPython runtime and start the script when it needs to map database values to an object. The hosting is also really simple:
T temporaryObject = new T();
//Register the engine globals
engine.DefaultModule.Globals.Add("ObjectUnderConstruction", temporaryObject);
engine.DefaultModule.Globals.Add("DataReader", reader);
engine.DefaultModule.Globals.Add("PropertyFieldDictionary", _selectPropertyFieldCache[objectType]);
string scriptContent = Encoding.Unicode.GetString(Properties.Resources.LoadPersistentObject);
engine.Execute(scriptContent);
result.Add(temporaryObject);
What's really fun about this is the fact that I can share my own variables inside the method with the IronPython script. This makes it easy for me to inject predefined variables into the script that I can manipulate there, the changes I made in the script are reflected back into the .NET environment.
Tomorrow I will be testing to see if my new version of the ObjectPersistenceHelper class is really faster than my old one. I hope it is, because that would open a new perspective of programming for me.
[1] http://wiki.cs.uiuc.edu/cs427/Python+-+Reflection