4 Mar
2012
Introduction
ClojureCLR is one of my favourite open source projects. It’s a port of Clojure to the CLR, the execution engine of the .NET platform. It’s a comprehensive port that includes almost all the features of the Java version. You can reuse any .NET assemblies from ClojureCLR, and because ClojureCLR produces regular .NET assemblies from your Clojure code, you can integrate with your existing programs written in other .NET languages. But even if you’re forced to keep writing code in another language, you can still leverage Clojure features, like its excellent concurrency support. (Something I’ll be writing about in a future post) That’s because Clojure isn’t just a language, it’s also a library.
Clojure proper is contained in a single jar file, which makes it dead easy for Java developers to include in their programs. ClojureCLR, unfortunately, spans 36 (!) assemblies, and if you’ve read Rob Rowe’s post Calling Clojure from C# you’ll have seen that you need to reference at least 10 assemblies from your C# program in order to call Clojure code. What’s worse, depending on the subset of features you use, it can be difficult to determine exactly which assemblies need to be referenced. Wouldn’t it be great if we could reduce the number of assemblies you need to reference to just one? Well, that’s exactly what I set out to do last week, and in this post I’ll be describing how I did it.
Assemblies as Embedded Resources
Say you try to load an assembly called MyAssembly by calling Assembly.Load("MyAssembly"); the CLR binder will look for MyAssembly in a few different places, in order:
- The GAC
- The application base directory
- The list of directories in the current AppDomain’s private bin path
If the binder fails to find MyAssembly in any of these places, it will raise an AssemblyResolve event. You can subscribe to this event to provide the assembly from another source, like an embedded resource. In my forked ClojureCLR repository I’ve added the following code to Lib/RT.cs:
Clojure.dll contains all the other ClojureCLR assemblies as embedded resources.

This however, isn’t enough. Since the ClojureCLR runtime loads assemblies dynamically, a change needs to be made to determine whether a given assembly can be loaded from an embedded resource, and then do so instead of looking for it on the load path. There are actually two overloads of RT.load; the first takes a relative assembly path as an argument and calls the second overload, which additionally takes a boolean specifying whether to raise an error if the assembly can’t be loaded. I modified the former to determine if the assembly is present as an embedded resource, and added an additional boolean argument to the latter, which if true, causes it to load the embedded assembly. Here’s the code, with some omissions for readability:
I also had to add an overload for Compiler.LoadAssembly that takes a byte array in place of a FileInfo object, and move the logic to a new method Compiler.InitAssembly that’s called by both overloads. And that’s pretty much the long and short of it. Now we just have one assembly to reference: Clojure.dll. (Strictly speaking this isn’t true, since you still have to reference the two DLR assemblies Microsoft.Scripting.dll and Microsoft.Dynamic.dll, but as far as ClojureCLR assemblies go, there is now only one)