Daniel Hoelbling-Inzko talks about programming

Using ILMerge to hide your dependencies

Posted by Daniel Hölbling on October 1, 2009

When developing a library that should be used by 3rd parties one major concern is dependency versioning. Meaning, if your code uses a common library like Castle.Windsor, things will get ugly if your users also use Castle.Windsor in another version.

Especially with very popular infrastructure libraries like Castle you can’t expect all your users not to use it, after all you’re probably using it for the same reason they do: Best of breed solution to a common problem.
To avoid trouble, many library authors decide not to take external dependencies so they won’t see versioning issues, while having to re-implement some infrastructure themselves.

Coming up with something simple usually isn’t that hard. If you just need a very limited feature set you can build your own Inversion of Control container quite easily without relying on external libraries. Yet, if you do you still have to spend time building, maintaining and extending the thing over time.

The other option is to use the fabulous tool ILMerge by Microsoft that allows you to munch multiple assemblies into one DLL. This is also handy if your product consists of many assemblies that you want to bundle, but in this case there is one cool thing ILMerge does: /internalize

ILMerge usually is called from the command line and works like this:

ILMerge.exe <main-assembly.dll> [<library1.dll> <library2.dll>] /out:<output-file.dll> /t:library

Now if you add the magic parameter /internalize ILmerge will hide all type names inside <library1.dll> and <library2.dll> from assemblies that reference the output assembly.

So in ElmsConnector’s case where Windsor is used internally the ILMerge call looks like this:


ElmsConnector-partial.dll is the original output dll from my msbuild process while ILMerge will merge all of these Castle assemblies into the output ElmsConnector.dll.
Now the real magic here is that if I open the resulting assembly in Reflector it still lists all Castle assemblies:


But inside Visual Studio none of the Castle.* namespaces exists because they are hidden.

This technique allows us to use our favorite tools in libraries without having to think too hard about versioning.

Now, obviously there are also some things to consider here:
If you want to expose any class that is inside one of the internalized assemblies, you have to tell ILMerge so through the exclude file (an example of this can be seen with Rhino.Mocks). Once you exclude one type and your users try to use that type they will see a “ambiguous type” compile-time error. That’s why Rhino.Mocks also comes in a unmerged flavor

Another thing to remember is (especially with web-apps) that your users can’t see any internalized assemblies, so any configuration you put into your web.config for them won’t work. Best example may be the PerWebRequest lifesyle for Windsor: It relies on a httpModule to be registered through the web.config, you can’t make that happen with the externalized assembly (and it leads to versioning problems once you exclude it).

Filed under net, programmierung, tools
comments powered by Disqus

My Photography business


dynamic css for .NET