IronRuby and the Configuration (app.config or exe.config)

I was trying to write a quick little IronRuby application that talks to a third-party library that I am working with. I ran into some problems related to configuration files, and I thought I would share how I got around the problem.[2]

The library I am working with requires that some values exist in the application’s configuration file, which could be either the app.config file or the executable_name.exe.config file. But I have no way to specify these values, because IronRuby’s ir.exe[1] has it’s own configuration, ir.exe.config that sets up paths and other options for the Dynamic Language Runtime (DLR). Any application that you execute with IronRuby is run within the context of ir.exe, and so it inherits ir.exe‘s configuration.

I should mention I could have added the values directly to ir.exe.config, but I dismissed this solution as unacceptable. I am really a stubborn person.

During my extensive research into the issue I encountered several suggested solutions, but none of them worked. Most discussions that I came across ended with someone giving up and modifying ir.exe.config.

The .NET Framework provides no approved way to modify the configuration once it is loaded into memory. I imagine that this is due to security issues. You would not want malicious code to get access to the configuration file and change the values. My second of two attempts to solve this problem resulted in success.

First, I tried creating a new AppDomain with its own configuration. However, I was not able to use any IronRuby constructs to get code to execute within the context of the child AppDomain.

To do this I first tried creating a MarshalByRef descendant that contained the code requiring the configuration settings. However, the way IronRuby creates CLR versions of the Ruby types made this very difficult. It looks like the types are created in an in memory assembly, but I could not get a reference to that assembly that would let me load my custom type into a different AppDomain. I kept getting errors complaining that the assembly could not be found. After hours of trying and trying I gave up and decided to call AppDomain.DoCallBack instead.

Here I encountered an issue with IronRuby delegates. I created a proc with the code that I wanted to execute and passed it into the constructor for the delegate type that is expected by the DoCallBack method. However, I got a really strange error complaining about not being able to serialize the delegate into the new AppDomain. Strike two. At this point giving up is starting to look like a really good option.

Not knowing another way to solve the problem, I decided to hack my way to a solution. With my friendly companion, Reflector, I started deciphering the logic that reads configuration files into memory. I wanted to find out how to change the configuration file that the current AppDomain is using and then force the AppDomain to read from the new configuration file. The result is the ConfigurationSettingsHackery class. It uses reflection to dig into System.Configuration and change some key private members. After doing so, the AppDomain re-reads the configuration the next time that configuration information is requested.

I hope this helps someone. It would have really been nice to have this class two days ago. I should warn you, however, that this is a nasty, nasty hack. As such, it it most likely not work on the next version of the .NET Framework.

[1]: I am using IronRuby 0.9.2.
[2]: This discussion is also applicable to IronPython users that are trying to do the same thing, as it has the same issues and limitations.


Leave a Reply