Bootstrapping Your Application From IronRuby
I think one of the best use cases for IronRuby is to use it as an automation tool and scripting platform for your domain application. The first hurdle I had to make this possible was Bootstrapping the application so that it can run from the IronRuby runtime. Among other things we need to initialize StructureMap and AutoMapper. Because you’re executing the IR.exe in it’s own AppDomain, there a couple of thing you have to do first.
Using StructureMap from IronRuby StructureMap can be loaded and accessed from IR without difficulty. But I find the syntax to use generic methods in IronRuby a bit noisy. So I made a simple module that wraps the StructureMap generic methods. We see these used in a minute.
require 'StructureMap' include StructureMap #module to hide the IronRuby generic noise module ObjectFactoryModule def get_instance type_name ObjectFactory.method(:get_instance).of(type_name).call end def inject(type,instance) ObjectFactory.method(:inject).of(type).call(instance) end def eject(type) ObjectFactory.method(:eject_all_instances_of).of(type).call end def replace(type,instance) ObjectFactory.method(:eject_all_instances_of).of(type).call ObjectFactory.method(:inject).of(type).call(instance) end end
Config files are your enemy
Because IronRuby runs in its own AppDomain, it is impossible to directly access your config files from IR without some serious hackery. But this it is not impossible to get around this if you encapsulate application settings behind an interface, with the default implementation getting values from configuration files. We have a very simple interface:
You can create a ruby class that implements the IApplicationSettings interface by including the interface.
require 'PropertyRegistration.Common' include PropertyRegistration::Common include ObjectFactoryModule class ScriptingApplicationSettings include IApplicationSettings def EventSourceDBConnectionString return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI' end def ViewModelConnectionString return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI' end def FasTrackDbConnectionString return 'Data Source=localhost;Initial Catalog=db;Integrated Security=SSPI' end def CurrentSessionContextClass return 'thread_static' end def ViewModelDefaultSchema return '[PropertyRegistration_ViewSource].[dbo]' end def LoadZipcodeDatabaseData return false end end
Now here’s the cool part we can inject the ruby class into structuremap so that it will be the implementation of IApplicationSettings.
$LOAD_PATH << File.dirname(__FILE__) + "/assemblies" require 'Rake' dlls = FileList.new(File.join(File.dirname(__FILE__),"assemblies/*.dll")) dlls.each {|f|require f} require 'StructureMap' require 'ObjectFactoryModule.rb' require 'ApplicationSettings.rb' require 'PropertyRegistration.DataLoader' include ObjectFactoryModule include PropertyRegistration::DataLoader::Application include StructureMap #bootstrapper, loading StructureMap registries and other stuff BootStrapper.startup settings = ScriptingApplicationSettings.new # ejecting IApplicationSettings and replacing with ruby class replace PropertyRegistration::Common::IApplicationSettings, settings
Now, we have loaded all of our assemblies, Called our bootstrapper to initialize StructureMap and everything else. Then we replaced the default implementation of IApplicationSettings with our Ruby implementation and our application is none the wiser. We can now use the IApplicationSettings from StructureMap as well as any classes that have it as a dependency.
exporter = get_instance(DataLoader::SchemaExporter)
exporter.generate_schema
There was more work involved getting everything to run from Rake, but this is the basic wiring and the other stuff is not really important.
I have bigger plans for using IronRuby with my applications. This was the first step. I’ll post more as my journey continues.